/* ** The cube() SQL function returns the cube of its input value. */ static void cubeFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { double r = sqlite3_value_double( argv[0] ); sqlite3_result_double( context, r * r * r ); }
/// <summary> /// This C function implements an SQL user function that is used by SQL code /// generated by the ALTER TABLE ... RENAME command to modify the definition /// of any foreign key constraints that use the table being renamed as the /// parent table. It is passed three arguments: /// /// 1) The complete text of the CREATE TABLE statement being modified, /// 2) The old name of the table being renamed, and /// 3) The new name of the table being renamed. /// /// It returns the new CREATE TABLE statement. For example: /// /// sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3') /// -> 'CREATE TABLE t1(a REFERENCES t3)' /// </summary> static void renameParentFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { sqlite3 db = sqlite3_context_db_handle(context); string zOutput = ""; string zResult; string zInput = sqlite3_value_text(argv[0]); string zOld = sqlite3_value_text(argv[1]); string zNew = sqlite3_value_text(argv[2]); int zIdx; /* Pointer to token */ int zLeft = 0; /* Pointer to remainder of String */ int n = 0; /* Length of token z */ int token = 0; /* Type of token */ UNUSED_PARAMETER(NotUsed); for (zIdx = 0; zIdx < zInput.Length; zIdx += n)//z=zInput; *z; z=z+n) { n = sqlite3GetToken(zInput, zIdx, ref token); if (token == TK_REFERENCES) { string zParent; do { zIdx += n; n = sqlite3GetToken(zInput, zIdx, ref token); } while (token == TK_SPACE); zParent = zIdx + n < zInput.Length ? zInput.Substring(zIdx, n) : "";//sqlite3DbStrNDup(db, zIdx, n); if (String.IsNullOrEmpty(zParent)) break; sqlite3Dequote(ref zParent); if (zOld.Equals(zParent, StringComparison.InvariantCultureIgnoreCase)) { string zOut = sqlite3MPrintf(db, "%s%.*s\"%w\"", zOutput, zIdx - zLeft, zInput.Substring(zLeft), zNew ); sqlite3DbFree(db, ref zOutput); zOutput = zOut; zIdx += n;// zInput = &z[n]; zLeft = zIdx; } sqlite3DbFree(db, ref zParent); } } zResult = sqlite3MPrintf(db, "%s%s", zOutput, zInput.Substring(zLeft)); sqlite3_result_text(context, zResult, -1, SQLITE_DYNAMIC); sqlite3DbFree(db, ref zOutput); }
/* ** Implementation of the abs() function. ** ** IMP: R-23979-26855 The abs(X) function returns the absolute value of ** the numeric argument X. */ static void absFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); switch ( sqlite3_value_type( argv[0] ) ) { case SQLITE_INTEGER: { i64 iVal = sqlite3_value_int64( argv[0] ); if ( iVal < 0 ) { if ( ( iVal << 1 ) == 0 ) { /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then ** abs(X) throws an integer overflow error since there is no ** equivalent positive 64-bit two complement value. */ sqlite3_result_error( context, "integer overflow", -1 ); return; } iVal = -iVal; } sqlite3_result_int64( context, iVal ); break; } case SQLITE_NULL: { /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */ sqlite3_result_null( context ); break; } default: { /* Because sqlite3_value_double() returns 0.0 if the argument is not ** something that can be converted into a number, we have: ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that ** cannot be converted to a numeric value. */ double rVal = sqlite3_value_double( argv[0] ); if ( rVal < 0 ) rVal = -rVal; sqlite3_result_double( context, rVal ); break; } } }
/* ** Implementation of randomblob(N). Return a random blob ** that is N bytes long. */ static void randomBlob( sqlite3_context context, int argc, sqlite3_value[] argv ) { int n; char[] p; Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); n = sqlite3_value_int( argv[0] ); if ( n < 1 ) { n = 1; } p = new char[n]; //contextMalloc( context, n ); if ( p != null ) { i64 _p = 0; for ( int i = 0; i < n; i++ ) { sqlite3_randomness( sizeof( u8 ), ref _p ); p[i] = (char)( _p & 0x7F ); } sqlite3_result_blob( context, new string( p ), n, null );//sqlite3_free ); } }
//#define ifnullFunc versionFunc /* Substitute function - never called */ /* ** Implementation of random(). Return a random integer. */ static void randomFunc( sqlite3_context context, int NotUsed, sqlite3_value[] NotUsed2 ) { sqlite_int64 r = 0; UNUSED_PARAMETER2( NotUsed, NotUsed2 ); sqlite3_randomness( sizeof( sqlite_int64 ), ref r ); if ( r < 0 ) { /* We need to prevent a random number of 0x8000000000000000 ** (or -9223372036854775808) since when you do abs() of that ** number of you get the same value back again. To do this ** in a way that is testable, mask the sign bit off of negative ** values, resulting in a positive value. Then take the ** 2s complement of that positive value. The end result can ** therefore be no less than -9223372036854775807. */ r = -( r ^ ( ( (sqlite3_int64)1 ) << 63 ) ); } sqlite3_result_int64( context, r ); }
/* ** Create a new sqlite3_value object, containing the value of pExpr. ** ** This only works for very simple expressions that consist of one constant ** token (i.e. "5", "5.1", "'a string'"). If the expression can ** be converted directly into a value, then the value is allocated and ** a pointer written to ppVal. The caller is responsible for deallocating ** the value by passing it to sqlite3ValueFree() later on. If the expression ** cannot be converted to a value, then ppVal is set to NULL. */ static int sqlite3ValueFromExpr( sqlite3 db, /* The database connection */ Expr pExpr, /* The expression to evaluate */ int enc, /* Encoding to use */ char affinity, /* Affinity to use */ ref sqlite3_value ppVal /* Write the new value here */ ) { int op; string zVal = ""; sqlite3_value pVal = null; int negInt = 1; string zNeg = ""; if ( pExpr == null ) { ppVal = null; return SQLITE_OK; } op = pExpr.op; /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT2. ** The ifdef here is to enable us to achieve 100% branch test coverage even ** when SQLITE_ENABLE_STAT2 is omitted. */ #if SQLITE_ENABLE_STAT2 if ( op == TK_REGISTER ) op = pExpr.op2; #else if( NEVER(op==TK_REGISTER) ) op = pExpr.op2; #endif /* Handle negative integers in a single step. This is needed in the ** case when the value is -9223372036854775808. */ if ( op == TK_UMINUS && ( pExpr.pLeft.op == TK_INTEGER || pExpr.pLeft.op == TK_FLOAT ) ) { pExpr = pExpr.pLeft; op = pExpr.op; negInt = -1; zNeg = "-"; } if ( op == TK_STRING || op == TK_FLOAT || op == TK_INTEGER ) { pVal = sqlite3ValueNew( db ); if ( pVal == null ) goto no_mem; if ( ExprHasProperty( pExpr, EP_IntValue ) ) { sqlite3VdbeMemSetInt64( pVal, (i64)pExpr.u.iValue * negInt ); } else { zVal = sqlite3MPrintf( db, "%s%s", zNeg, pExpr.u.zToken ); //if ( zVal == null ) goto no_mem; sqlite3ValueSetStr( pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC ); if ( op == TK_FLOAT ) pVal.type = SQLITE_FLOAT; } if ( ( op == TK_INTEGER || op == TK_FLOAT ) && affinity == SQLITE_AFF_NONE ) { sqlite3ValueApplyAffinity( pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8 ); } else { sqlite3ValueApplyAffinity( pVal, affinity, SQLITE_UTF8 ); } if ( ( pVal.flags & ( MEM_Int | MEM_Real ) ) != 0 ) pVal.flags = (ushort)( pVal.flags & ~MEM_Str ); if ( enc != SQLITE_UTF8 ) { sqlite3VdbeChangeEncoding( pVal, enc ); } } if ( enc != SQLITE_UTF8 ) { sqlite3VdbeChangeEncoding( pVal, enc ); } else if ( op == TK_UMINUS ) { /* This branch happens for multiple negative signs. Ex: -(-5) */ if ( SQLITE_OK == sqlite3ValueFromExpr( db, pExpr.pLeft, enc, affinity, ref pVal ) ) { sqlite3VdbeMemNumerify( pVal ); pVal.u.i = -1 * pVal.u.i; /* (double)-1 In case of SQLITE_OMIT_FLOATING_POINT... */ pVal.r = (double)-1 * pVal.r; sqlite3ValueApplyAffinity( pVal, affinity, enc ); } else if ( op == TK_NULL ) { pVal = sqlite3ValueNew( db ); if ( pVal == null ) goto no_mem; } } #if !SQLITE_OMIT_BLOB_LITERAL else if ( op == TK_BLOB ) { int nVal; Debug.Assert( pExpr.u.zToken[0] == 'x' || pExpr.u.zToken[0] == 'X' ); Debug.Assert( pExpr.u.zToken[1] == '\'' ); pVal = sqlite3ValueNew( db ); if ( null == pVal ) goto no_mem; zVal = pExpr.u.zToken.Substring( 2 ); nVal = sqlite3Strlen30( zVal ) - 1; Debug.Assert( zVal[nVal] == '\'' ); byte[] blob = sqlite3HexToBlob( db, zVal, nVal ); sqlite3VdbeMemSetStr( pVal, Encoding.UTF8.GetString( blob, 0, blob.Length ), nVal / 2, 0, SQLITE_DYNAMIC ); } #endif if ( pVal != null ) { sqlite3VdbeMemStoreType( pVal ); } ppVal = pVal; return SQLITE_OK; no_mem: //db.mallocFailed = 1; sqlite3DbFree( db, ref zVal ); pVal = null;// sqlite3ValueFree(pVal); ppVal = null; return SQLITE_NOMEM; }
/* ** group_concat(EXPR, ?SEPARATOR?) */ static void groupConcatStep( sqlite3_context context, int argc, sqlite3_value[] argv ) { string zVal; //StrAccum pAccum; string zSep; int nVal, nSep; Debug.Assert( argc == 1 || argc == 2 ); if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) return; Mem pMem = sqlite3_aggregate_context( context, 1 );//sizeof(*pAccum)); if ( pMem._StrAccum == null ) pMem._StrAccum = new StrAccum( 100 ); //pAccum = pMem._StrAccum; //if ( pMem._StrAccum != null ) //{ sqlite3 db = sqlite3_context_db_handle( context ); //int firstTerm = pMem._StrAccum.useMalloc == 0 ? 1 : 0; //pMem._StrAccum.useMalloc = 2; pMem._StrAccum.mxAlloc = db.aLimit[SQLITE_LIMIT_LENGTH]; if ( pMem._StrAccum.Context == null ) // first term pMem._StrAccum.Context = pMem; else { if ( argc == 2 ) { zSep = sqlite3_value_text( argv[1] ); nSep = sqlite3_value_bytes( argv[1] ); } else { zSep = ","; nSep = 1; } sqlite3StrAccumAppend( pMem._StrAccum, zSep, nSep ); } zVal = sqlite3_value_text( argv[0] ); nVal = sqlite3_value_bytes( argv[0] ); sqlite3StrAccumAppend( pMem._StrAccum, zVal, nVal ); //} }
/* ** 2005 February 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 ** ************************************************************************* */ //#include "sqliteInt.h" /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ /// <summary> /// This function is used by SQL generated to implement the /// ALTER TABLE command. The first argument is the text of a CREATE TABLE or /// CREATE INDEX command. The second is a table name. The table name in /// the CREATE TABLE or CREATE INDEX statement is replaced with the third /// argument and the result returned. Examples: /// /// sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') /// . 'CREATE TABLE def(a, b, c)' /// /// sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') /// . 'CREATE INDEX i ON def(a, b, c)' /// </summary> static void renameTableFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { string bResult = sqlite3_value_text(argv[0]); string zSql = bResult == null ? "" : bResult; string zTableName = sqlite3_value_text(argv[1]); int token = 0; Token tname = new Token(); int zCsr = 0; int zLoc = 0; int len = 0; string zRet; sqlite3 db = sqlite3_context_db_handle(context); UNUSED_PARAMETER(NotUsed); /* The principle used to locate the table name in the CREATE TABLE ** statement is that the table name is the first non-space token that ** is immediately followed by a TK_LP or TK_USING token. */ if (zSql != "") { do { if (zCsr == zSql.Length) { /* Ran out of input before finding an opening bracket. Return NULL. */ return; } /* Store the token that zCsr points to in tname. */ zLoc = zCsr; tname.z = zSql.Substring(zCsr);//(char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = (zCsr == zSql.Length) ? 1 : sqlite3GetToken(zSql, zCsr, ref token); } while (token == TK_SPACE); Debug.Assert(len > 0); } while (token != TK_LP && token != TK_USING); zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", zLoc, zSql.Substring(0, zLoc), zTableName, zSql.Substring(zLoc + tname.n)); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } }
/* ** Return the number of bytes in the sqlite3_value object assuming ** that it uses the encoding "enc" */ static int sqlite3ValueBytes( sqlite3_value pVal, int enc ) { Mem p = (Mem)pVal; if ( ( p.flags & MEM_Blob ) != 0 || sqlite3ValueText( pVal, enc ) != null ) { if ( ( p.flags & MEM_Zero ) != 0 ) { return p.n + p.u.nZero; } else { return p.z == null ? p.zBLOB.Length : p.n; } } return 0; }
static void lowerFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { string z1; string z2; int i, n; UNUSED_PARAMETER( argc ); z2 = sqlite3_value_text( argv[0] ); n = sqlite3_value_bytes( argv[0] ); /* Verify that the call to _bytes() does not invalidate the _text() pointer */ //Debug.Assert( z2 == sqlite3_value_text( argv[0] ) ); if ( z2 != null ) { //z1 = contextMalloc(context, ((i64)n)+1); //if ( z1 ) //{ // memcpy( z1, z2, n + 1 ); // for ( i = 0 ; z1[i] ; i++ ) // { // z1[i] = (char)sqlite3Tolower( z1[i] ); // } sqlite3_result_text( context, z2.Length == 0 ? "" : z2.Substring( 0, n ).ToLower(), -1, null );//sqlite3_free ); //} } }
/* ** An SQL user-function registered to do the work of an DETACH statement. The ** three arguments to the function come directly from a detach statement: ** ** DETACH DATABASE x ** ** SELECT sqlite_detach(x) */ static void detachFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { string zName = zName = argv[0].z != null && ( argv[0].z.Length > 0 ) ? sqlite3_value_text( argv[0] ) : "";//(sqlite3_value_text(argv[0]); sqlite3 db = sqlite3_context_db_handle( context ); int i; Db pDb = null; StringBuilder zErr = new StringBuilder( 200 ); UNUSED_PARAMETER( NotUsed ); if ( zName == null ) zName = ""; for ( i = 0; i < db.nDb; i++ ) { pDb = db.aDb[i]; if ( pDb.pBt == null ) continue; if ( pDb.zName.Equals( zName, StringComparison.InvariantCultureIgnoreCase ) ) break; } if ( i >= db.nDb ) { sqlite3_snprintf( 200, zErr, "no such database: %s", zName ); goto detach_error; } if ( i < 2 ) { sqlite3_snprintf( 200, zErr, "cannot detach database %s", zName ); goto detach_error; } if ( 0 == db.autoCommit ) { sqlite3_snprintf( 200, zErr, "cannot DETACH database within transaction" ); goto detach_error; } if ( sqlite3BtreeIsInReadTrans( pDb.pBt ) || sqlite3BtreeIsInBackup( pDb.pBt ) ) { sqlite3_snprintf( 200, zErr, "database %s is locked", zName ); goto detach_error; } sqlite3BtreeClose( ref pDb.pBt ); pDb.pBt = null; pDb.pSchema = null; sqlite3ResetInternalSchema( db, 0 ); return; detach_error: sqlite3_result_error( context, zErr.ToString(), -1 ); }
/* ** Implementation of the length() function */ static void lengthFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int len; Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); switch ( sqlite3_value_type( argv[0] ) ) { case SQLITE_BLOB: case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_int( context, sqlite3_value_bytes( argv[0] ) ); break; } case SQLITE_TEXT: { byte[] z = sqlite3_value_blob( argv[0] ); if ( z == null ) return; len = 0; int iz = 0; while ( iz < z.Length && z[iz] != '\0' ) { len++; SQLITE_SKIP_UTF8( z, ref iz ); } sqlite3_result_int( context, len ); break; } default: { sqlite3_result_null( context ); break; } } }
/* ** Implementation of the like() SQL function. This function implements ** the build-in LIKE operator. The first argument to the function is the ** pattern and the second argument is the string. So, the SQL statements: ** ** A LIKE B ** ** is implemented as like(B,A). ** ** This same function (with a different compareInfo structure) computes ** the GLOB operator. */ static void likeFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { string zA, zB; int escape = 0; int nPat; sqlite3 db = sqlite3_context_db_handle( context ); zB = sqlite3_value_text( argv[0] ); zA = sqlite3_value_text( argv[1] ); /* Limit the length of the LIKE or GLOB pattern to avoid problems ** of deep recursion and N*N behavior in patternCompare(). */ nPat = sqlite3_value_bytes( argv[0] ); testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ); testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] + 1 ); if ( nPat > db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] ) { sqlite3_result_error( context, "LIKE or GLOB pattern too complex", -1 ); return; } //Debug.Assert( zB == sqlite3_value_text( argv[0] ) ); /* Encoding did not change */ if ( argc == 3 ) { /* The escape character string must consist of a single UTF-8 character. ** Otherwise, return an error. */ string zEsc = sqlite3_value_text( argv[2] ); if ( zEsc == null ) return; if ( sqlite3Utf8CharLen( zEsc, -1 ) != 1 ) { sqlite3_result_error( context, "ESCAPE expression must be a single character", -1 ); return; } escape = sqlite3Utf8Read( zEsc, ref zEsc ); } if ( zA != null && zB != null ) { compareInfo pInfo = (compareInfo)sqlite3_user_data( context ); #if SQLITE_TEST sqlite3_like_count.iValue++; #endif sqlite3_result_int( context, patternCompare( zB, zA, pInfo, escape ) ? 1 : 0 ); } }
/* ** Implementation of the last_insert_rowid() SQL function. The return ** value is the same as the sqlite3_last_insert_rowid() API function. */ static void last_insert_rowid( sqlite3_context context, int NotUsed, sqlite3_value[] NotUsed2 ) { sqlite3 db = sqlite3_context_db_handle( context ); UNUSED_PARAMETER2( NotUsed, NotUsed2 ); /* IMP: R-51513-12026 The last_insert_rowid() SQL function is a ** wrapper around the sqlite3_last_insert_rowid() C/C++ interface ** function. */ sqlite3_result_int64( context, sqlite3_last_insert_rowid( db ) ); }
/* ** The hex() function. Interpret the argument as a blob. Return ** a hexadecimal rendering as text. */ static void hexFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int i, n; byte[] pBlob; //string zHex, z; Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); pBlob = sqlite3_value_blob( argv[0] ); n = sqlite3_value_bytes( argv[0] ); Debug.Assert( n == ( pBlob == null ? 0 : pBlob.Length ) ); /* No encoding change */ StringBuilder zHex = new StringBuilder( n * 2 + 1 ); // z = zHex = contextMalloc(context, ((i64)n)*2 + 1); if ( zHex != null ) { for ( i = 0; i < n; i++ ) {//, pBlob++){ byte c = pBlob[i]; zHex.Append( hexdigits[( c >> 4 ) & 0xf] ); zHex.Append( hexdigits[c & 0xf] ); } sqlite3_result_text( context, zHex, n * 2, null ); //sqlite3_free ); } }
/* IMP: R-25361-16150 This function is omitted from SQLite by default. It ** is only available if the SQLITE_SOUNDEX compile-time option is used ** when SQLite is built. */ /* ** Compute the soundex encoding of a word. ** ** IMP: R-59782-00072 The soundex(X) function returns a string that is the ** soundex encoding of the string X. */ static void soundexFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { Debug.Assert(false); // TODO -- func_c char zResult[8];
/* ** The replace() function. Three arguments are all strings: call ** them A, B, and C. The result is also a string which is derived ** from A by replacing every occurance of B with C. The match ** must be exact. Collating sequences are not used. */ static void replaceFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { string zStr; /* The input string A */ string zPattern; /* The pattern string B */ string zRep; /* The replacement string C */ string zOut; /* The output */ int nStr; /* Size of zStr */ int nPattern; /* Size of zPattern */ int nRep; /* Size of zRep */ int nOut; /* Maximum size of zOut */ //int loopLimit; /* Last zStr[] that might match zPattern[] */ int i, j; /* Loop counters */ Debug.Assert( argc == 3 ); UNUSED_PARAMETER( argc ); zStr = sqlite3_value_text( argv[0] ); if ( zStr == null ) return; nStr = sqlite3_value_bytes( argv[0] ); Debug.Assert( zStr == sqlite3_value_text( argv[0] ) ); /* No encoding change */ zPattern = sqlite3_value_text( argv[1] ); if ( zPattern == null ) { Debug.Assert( sqlite3_value_type( argv[1] ) == SQLITE_NULL //|| sqlite3_context_db_handle( context ).mallocFailed != 0 ); return; } if ( zPattern == "" ) { Debug.Assert( sqlite3_value_type( argv[1] ) != SQLITE_NULL ); sqlite3_result_value( context, argv[0] ); return; } nPattern = sqlite3_value_bytes( argv[1] ); Debug.Assert( zPattern == sqlite3_value_text( argv[1] ) ); /* No encoding change */ zRep = sqlite3_value_text( argv[2] ); if ( zRep == null ) return; nRep = sqlite3_value_bytes( argv[2] ); Debug.Assert( zRep == sqlite3_value_text( argv[2] ) ); nOut = nStr + 1; Debug.Assert( nOut < SQLITE_MAX_LENGTH ); //zOut = contextMalloc(context, (i64)nOut); //if( zOut==0 ){ // return; //} //loopLimit = nStr - nPattern; //for(i=j=0; i<=loopLimit; i++){ // if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ // zOut[j++] = zStr[i]; // }else{ // u8 *zOld; // sqlite3 db = sqlite3_context_db_handle( context ); // nOut += nRep - nPattern; //testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); //testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); //if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ // sqlite3_result_error_toobig(context); // sqlite3_free(zOut); // return; // } // zOld = zOut; // zOut = sqlite3_realloc(zOut, (int)nOut); // if( zOut==0 ){ // sqlite3_result_error_nomem(context); // sqlite3_free(zOld); // return; // } // memcpy(&zOut[j], zRep, nRep); // j += nRep; // i += nPattern-1; // } //} //Debug.Assert( j+nStr-i+1==nOut ); //memcpy(&zOut[j], zStr[i], nStr-i); //j += nStr - i; //Debug.Assert( j<=nOut ); //zOut[j] = 0; zOut = zStr.Replace( zPattern, zRep ); j = zOut.Length; sqlite3_result_text( context, zOut, j, null );//sqlite3_free ); }
/* ** Implementation of the non-aggregate min() and max() functions */ static void minmaxFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int i; int mask; /* 0 for min() or 0xffffffff for max() */ int iBest; CollSeq pColl; Debug.Assert( argc > 1 ); mask = (int)sqlite3_user_data( context ) == 0 ? 0 : -1; pColl = sqlite3GetFuncCollSeq( context ); Debug.Assert( pColl != null ); Debug.Assert( mask == -1 || mask == 0 ); testcase( mask == 0 ); iBest = 0; if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) return; for ( i = 1; i < argc; i++ ) { if ( sqlite3_value_type( argv[i] ) == SQLITE_NULL ) return; if ( ( sqlite3MemCompare( argv[iBest], argv[i], pColl ) ^ mask ) >= 0 ) { iBest = i; } } sqlite3_result_value( context, argv[iBest] ); }
/* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: ** ** ATTACH DATABASE x AS y KEY z ** ** SELECT sqlite_attach(x, y, z) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. */ static void attachFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { int i; int rc = 0; sqlite3 db = sqlite3_context_db_handle( context ); string zName; string zFile; Db aNew = null; string zErrDyn = ""; UNUSED_PARAMETER( NotUsed ); zFile = argv[0].z != null && ( argv[0].z.Length > 0 ) && argv[0].flags != MEM_Null ? sqlite3_value_text( argv[0] ) : ""; zName = argv[1].z != null && ( argv[1].z.Length > 0 ) && argv[1].flags != MEM_Null ? sqlite3_value_text( argv[1] ) : ""; //if( zFile==null ) zFile = ""; //if ( zName == null ) zName = ""; /* Check for the following errors: ** ** * Too many attached databases, ** * Transaction currently open ** * Specified database name already being used. */ if ( db.nDb >= db.aLimit[SQLITE_LIMIT_ATTACHED] + 2 ) { zErrDyn = sqlite3MPrintf( db, "too many attached databases - max %d", db.aLimit[SQLITE_LIMIT_ATTACHED] ); goto attach_error; } if ( 0 == db.autoCommit ) { zErrDyn = sqlite3MPrintf( db, "cannot ATTACH database within transaction" ); goto attach_error; } for ( i = 0; i < db.nDb; i++ ) { string z = db.aDb[i].zName; Debug.Assert( z != null && zName != null ); if ( z.Equals( zName, StringComparison.InvariantCultureIgnoreCase ) ) { zErrDyn = sqlite3MPrintf( db, "database %s is already in use", zName ); goto attach_error; } } /* Allocate the new entry in the db.aDb[] array and initialise the schema ** hash tables. */ /* Allocate the new entry in the db.aDb[] array and initialise the schema ** hash tables. */ //if( db.aDb==db.aDbStatic ){ // aNew = sqlite3DbMallocRaw(db, sizeof(db.aDb[0])*3 ); // if( aNew==0 ) return; // memcpy(aNew, db.aDb, sizeof(db.aDb[0])*2); //}else { if ( db.aDb.Length <= db.nDb ) Array.Resize( ref db.aDb, db.nDb + 1 );//aNew = sqlite3DbRealloc(db, db.aDb, sizeof(db.aDb[0])*(db.nDb+1) ); if ( db.aDb == null ) return; // if( aNew==0 ) return; //} db.aDb[db.nDb] = new Db();//db.aDb = aNew; aNew = db.aDb[db.nDb];//memset(aNew, 0, sizeof(*aNew)); // memset(aNew, 0, sizeof(*aNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may ** or may not be initialised. */ rc = sqlite3BtreeOpen( zFile, db, ref aNew.pBt, 0, db.openFlags | SQLITE_OPEN_MAIN_DB ); db.nDb++; if ( rc == SQLITE_CONSTRAINT ) { rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf( db, "database is already attached" ); } else if ( rc == SQLITE_OK ) { Pager pPager; aNew.pSchema = sqlite3SchemaGet( db, aNew.pBt ); if ( aNew.pSchema == null ) { rc = SQLITE_NOMEM; } else if ( aNew.pSchema.file_format != 0 && aNew.pSchema.enc != ENC( db ) ) { zErrDyn = sqlite3MPrintf( db, "attached databases must use the same text encoding as main database" ); rc = SQLITE_ERROR; } pPager = sqlite3BtreePager( aNew.pBt ); sqlite3PagerLockingMode( pPager, db.dfltLockMode ); sqlite3BtreeSecureDelete( aNew.pBt, sqlite3BtreeSecureDelete( db.aDb[0].pBt, -1 ) ); } aNew.safety_level = 3; aNew.zName = zName;//sqlite3DbStrDup(db, zName); //if( rc==SQLITE_OK && aNew.zName==0 ){ // rc = SQLITE_NOMEM; //} #if SQLITE_HAS_CODEC if ( rc == SQLITE_OK ) { //extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); //extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; string zKey; int t = sqlite3_value_type( argv[2] ); switch ( t ) { case SQLITE_INTEGER: case SQLITE_FLOAT: zErrDyn = "Invalid key value"; //sqlite3DbStrDup( db, "Invalid key value" ); rc = SQLITE_ERROR; break; case SQLITE_TEXT: case SQLITE_BLOB: nKey = sqlite3_value_bytes( argv[2] ); zKey = sqlite3_value_blob( argv[2] ).ToString(); // (char *)sqlite3_value_blob(argv[2]); rc = sqlite3CodecAttach( db, db.nDb - 1, zKey, nKey ); break; case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey( db, 0, out zKey, out nKey ); //sqlite3CodecGetKey(db, 0, (void**)&zKey, nKey); rc = sqlite3CodecAttach( db, db.nDb - 1, zKey, nKey ); break; } } #endif /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and ** remove the entry from the db.aDb[] array. i.e. put everything back the way ** we found it. */ if ( rc == SQLITE_OK ) { sqlite3BtreeEnterAll( db ); rc = sqlite3Init( db, ref zErrDyn ); sqlite3BtreeLeaveAll( db ); } if ( rc != 0 ) { int iDb = db.nDb - 1; Debug.Assert( iDb >= 2 ); if ( db.aDb[iDb].pBt != null ) { sqlite3BtreeClose( ref db.aDb[iDb].pBt ); db.aDb[iDb].pBt = null; db.aDb[iDb].pSchema = null; } sqlite3ResetInternalSchema( db, 0 ); db.nDb = iDb; if ( rc == SQLITE_NOMEM || rc == SQLITE_IOERR_NOMEM ) { //// db.mallocFailed = 1; sqlite3DbFree( db, ref zErrDyn ); zErrDyn = sqlite3MPrintf( db, "out of memory" ); } else if ( zErrDyn == "" ) { zErrDyn = sqlite3MPrintf( db, "unable to open database: %s", zFile ); } goto attach_error; } return; attach_error: /* Return an error if we get here */ if ( zErrDyn != "" ) { sqlite3_result_error( context, zErrDyn, -1 ); sqlite3DbFree( db, ref zErrDyn ); } if ( rc != 0 ) sqlite3_result_error_code( context, rc ); }
/* ** Routines to implement min() and max() aggregate functions. */ static void minmaxStep( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { Mem pArg = (Mem)argv[0]; Mem pBest; UNUSED_PARAMETER( NotUsed ); if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) return; pBest = (Mem)sqlite3_aggregate_context( context, 1 );//sizeof(*pBest)); //if ( pBest == null ) return; if ( pBest.flags != 0 ) { bool max; int cmp; CollSeq pColl = sqlite3GetFuncCollSeq( context ); /* This step function is used for both the min() and max() aggregates, ** the only difference between the two being that the sense of the ** comparison is inverted. For the max() aggregate, the ** sqlite3_context_db_handle() function returns (void *)-1. For min() it ** returns (void *)db, where db is the sqlite3* database pointer. ** Therefore the next statement sets variable 'max' to 1 for the max() ** aggregate, or 0 for min(). */ max = sqlite3_context_db_handle( context ) != null && (int)sqlite3_user_data( context ) != 0; cmp = sqlite3MemCompare( pBest, pArg, pColl ); if ( ( max && cmp < 0 ) || ( !max && cmp > 0 ) ) { sqlite3VdbeMemCopy( pBest, pArg ); } } else { sqlite3VdbeMemCopy( pBest, pArg ); } }
/// <summary> /// This function is used by SQL generated to implement the /// ALTER TABLE command. The first argument is the text of a CREATE TRIGGER /// statement. The second is a table name. The table name in the CREATE /// TRIGGER statement is replaced with the third argument and the result /// returned. This is analagous to renameTableFunc() above, except for CREATE /// TRIGGER, not CREATE INDEX and CREATE TABLE. /// </summary> static void renameTriggerFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { string zSql = sqlite3_value_text(argv[0]); string zTableName = sqlite3_value_text(argv[1]); int token = 0; Token tname = new Token(); int dist = 3; int zCsr = 0; int zLoc = 0; int len = 1; string zRet; sqlite3 db = sqlite3_context_db_handle(context); UNUSED_PARAMETER(NotUsed); /* The principle used to locate the table name in the CREATE TRIGGER ** statement is that the table name is the first token that is immediatedly ** preceded by either TK_ON or TK_DOT and immediatedly followed by one ** of TK_WHEN, TK_BEGIN or TK_FOR. */ if (zSql != null) { do { if (zCsr == zSql.Length) { /* Ran out of input before finding the table name. Return NULL. */ return; } /* Store the token that zCsr points to in tname. */ zLoc = zCsr; tname.z = zSql.Substring(zCsr, len);//(char*)zCsr; tname.n = len; /* Advance zCsr to the next token. Store that token type in 'token', ** and its length in 'len' (to be used next iteration of this loop). */ do { zCsr += len; len = (zCsr == zSql.Length) ? 1 : sqlite3GetToken(zSql, zCsr, ref token); } while (token == TK_SPACE); Debug.Assert(len > 0); /* Variable 'dist' stores the number of tokens read since the most ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN ** token is read and 'dist' equals 2, the condition stated above ** to be met. ** ** Note that ON cannot be a database, table or column name, so ** there is no need to worry about syntax like ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. */ dist++; if (token == TK_DOT || token == TK_ON) { dist = 0; } } while (dist != 2 || (token != TK_WHEN && token != TK_FOR && token != TK_BEGIN)); /* Variable tname now contains the token that is the old table-name ** in the CREATE TRIGGER statement. */ zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", zLoc, zSql.Substring(0, zLoc), zTableName, zSql.Substring(zLoc + tname.n)); sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC); } }
/* ** Implementation of the NULLIF(x,y) function. The result is the first ** argument if the arguments are different. The result is NULL if the ** arguments are equal to each other. */ static void nullifFunc( sqlite3_context context, int NotUsed, sqlite3_value[] argv ) { CollSeq pColl = sqlite3GetFuncCollSeq( context ); UNUSED_PARAMETER( NotUsed ); if ( sqlite3MemCompare( argv[0], argv[1], pColl ) != 0 ) { sqlite3_result_value( context, argv[0] ); } }
/* ** Count the number of times that the LIKE operator (or GLOB which is ** just a variation of LIKE) gets called. This is used for testing ** only. */ //static int sqlite3_like_count = 0; #endif #if !SQLITE_OMIT_COMPILEOPTION_DIAGS /* ** Implementation of the sqlite_compileoption_used() function. ** The result is an integer that identifies if the compiler option ** was used to build SQLite. */ static void compileoptionusedFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { string zOptName; Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL ** function is a wrapper around the sqlite3_compileoption_used() C/C++ ** function. */ if ( ( zOptName = sqlite3_value_text( argv[0] ) ) != null ) { sqlite3_result_int( context, sqlite3_compileoption_used( zOptName ) ); } }
/* This function is only available internally, it is not part of the ** external API. It works in a similar way to sqlite3_value_text(), ** except the data returned is in the encoding specified by the second ** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or ** SQLITE_UTF8. ** ** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED. ** If that is the case, then the result must be aligned on an even byte ** boundary. */ static string sqlite3ValueText( sqlite3_value pVal, int enc ) { if ( pVal == null ) return null; Debug.Assert( pVal.db == null || sqlite3_mutex_held( pVal.db.mutex ) ); Debug.Assert( ( enc & 3 ) == ( enc & ~SQLITE_UTF16_ALIGNED ) ); Debug.Assert( ( pVal.flags & MEM_RowSet ) == 0 ); if ( ( pVal.flags & MEM_Null ) != 0 ) { return null; } Debug.Assert( ( MEM_Blob >> 3 ) == MEM_Str ); pVal.flags |= (u16)( ( pVal.flags & MEM_Blob ) >> 3 ); if ( ( pVal.flags & MEM_Zero ) != 0 ) sqlite3VdbeMemExpandBlob( pVal ); // expandBlob(pVal); if ( ( pVal.flags & MEM_Str ) != 0 ) { sqlite3VdbeChangeEncoding( pVal, enc & ~SQLITE_UTF16_ALIGNED ); if ( ( enc & SQLITE_UTF16_ALIGNED ) != 0 && 1 == ( 1 & ( pVal.z[0] ) ) ) //1==(1&SQLITE_PTR_TO_INT(pVal.z)) { Debug.Assert( ( pVal.flags & ( MEM_Ephem | MEM_Static ) ) != 0 ); if ( sqlite3VdbeMemMakeWriteable( pVal ) != SQLITE_OK ) { return null; } } sqlite3VdbeMemNulTerminate( pVal ); /* IMP: R-59893-45467 */ } else { Debug.Assert( ( pVal.flags & MEM_Blob ) == 0 ); sqlite3VdbeMemStringify( pVal, enc ); // assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) ); } Debug.Assert( pVal.enc == ( enc & ~SQLITE_UTF16_ALIGNED ) || pVal.db == null //|| pVal.db.mallocFailed != 0 ); if ( pVal.enc == ( enc & ~SQLITE_UTF16_ALIGNED ) ) { return pVal.z; } else { return null; } }
/* ** Free an sqlite3_value object */ static void sqlite3ValueFree( ref sqlite3_value v ) { if ( v == null ) return; sqlite3VdbeMemRelease( v ); sqlite3DbFree( v.db, ref v ); }
/* ** The COALESCE() and IFNULL() functions used to be implemented as shown ** here. But now they are implemented as VDBE code so that unused arguments ** do not have to be computed. This legacy implementation is retained as ** comment. */ /* ** Implementation of the IFNULL(), NVL(), and COALESCE() functions. ** All three do the same thing. They return the first non-NULL ** argument. */ static void ifnullFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int i; for ( i = 0 ; i < argc ; i++ ) { if ( SQLITE_NULL != sqlite3_value_type( argv[i] ) ) { sqlite3_result_value( context, argv[i] ); break; } } }
/* ** Change the string value of an sqlite3_value object */ static void sqlite3ValueSetStr( sqlite3_value v, /* Value to be set */ int n, /* Length of string z */ string z, /* Text of the new string */ u8 enc, /* Encoding to use */ dxDel xDel//)(void*) /* Destructor for the string */ ) { if ( v != null ) sqlite3VdbeMemSetStr( v, z, n, enc, xDel ); }
/* ** Implementation of the sqlite_compileoption_get() function. ** The result is a string that identifies the compiler options ** used to build SQLite. */ static void compileoptiongetFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int n; Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function ** is a wrapper around the sqlite3_compileoption_get() C/C++ function. */ n = sqlite3_value_int( argv[0] ); sqlite3_result_text( context, sqlite3_compileoption_get( n ), -1, SQLITE_STATIC ); }
/* ** EXPERIMENTAL - This is not an official function. The interface may ** change. This function may disappear. Do not write code that depends ** on this function. ** ** Implementation of the QUOTE() function. This function takes a single ** argument. If the argument is numeric, the return value is the same as ** the argument. If the argument is NULL, the return value is the string ** "NULL". Otherwise, the argument is enclosed in single quotes with ** single-quote escapes. */ static void quoteFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { Debug.Assert( argc == 1 ); UNUSED_PARAMETER( argc ); switch ( sqlite3_value_type( argv[0] ) ) { case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_value( context, argv[0] ); break; } case SQLITE_BLOB: { StringBuilder zText; byte[] zBlob = sqlite3_value_blob( argv[0] ); int nBlob = sqlite3_value_bytes( argv[0] ); Debug.Assert( zBlob.Length == sqlite3_value_blob( argv[0] ).Length ); /* No encoding change */ zText = new StringBuilder( 2 * nBlob + 4 );//(char*)contextMalloc(context, (2*(i64)nBlob)+4); zText.Append( "X'" ); if ( zText != null ) { int i; for ( i = 0; i < nBlob; i++ ) { zText.Append( hexdigits[( zBlob[i] >> 4 ) & 0x0F] ); zText.Append( hexdigits[( zBlob[i] ) & 0x0F] ); } zText.Append( "'" ); //zText[( nBlob * 2 ) + 2] = '\''; //zText[( nBlob * 2 ) + 3] = '\0'; //zText[0] = 'X'; //zText[1] = '\''; sqlite3_result_text( context, zText, -1, SQLITE_TRANSIENT ); //sqlite3_free( zText ); } break; } case SQLITE_TEXT: { int i, j; int n; string zArg = sqlite3_value_text( argv[0] ); StringBuilder z; if ( zArg == null || zArg.Length == 0 ) return; for ( i = 0, n = 0; i < zArg.Length; i++ ) { if ( zArg[i] == '\'' ) n++; } z = new StringBuilder( i + n + 3 );// contextMalloc(context, ((i64)i)+((i64)n)+3); if ( z != null ) { z.Append( '\'' ); for ( i = 0, j = 1; i < zArg.Length && zArg[i] != 0; i++ ) { z.Append( (char)zArg[i] ); j++; if ( zArg[i] == '\'' ) { z.Append( '\'' ); j++; } } z.Append( '\'' ); j++; //z[j] = '\0'; ; sqlite3_result_text( context, z, j, null );//sqlite3_free ); } break; } default: { Debug.Assert( sqlite3_value_type( argv[0] ) == SQLITE_NULL ); sqlite3_result_text( context, "NULL", 4, SQLITE_STATIC ); break; } } }
/* ** Implementation of the round() function */ static void roundFunc( sqlite3_context context, int argc, sqlite3_value[] argv ) { int n = 0; double r; string zBuf = ""; Debug.Assert( argc == 1 || argc == 2 ); if ( argc == 2 ) { if ( SQLITE_NULL == sqlite3_value_type( argv[1] ) ) return; n = sqlite3_value_int( argv[1] ); if ( n > 30 ) n = 30; if ( n < 0 ) n = 0; } if ( sqlite3_value_type( argv[0] ) == SQLITE_NULL ) return; r = sqlite3_value_double( argv[0] ); /* If Y==0 and X will fit in a 64-bit int, ** handle the rounding directly, ** otherwise use printf. */ if ( n == 0 && r >= 0 && r < LARGEST_INT64 - 1 ) { r = (double)( (sqlite_int64)( r + 0.5 ) ); } else if ( n == 0 && r < 0 && ( -r ) < LARGEST_INT64 - 1 ) { r = -(double)( (sqlite_int64)( ( -r ) + 0.5 ) ); } else { zBuf = sqlite3_mprintf( "%.*f", n, r ); if ( zBuf == null ) { sqlite3_result_error_nomem( context ); return; } sqlite3AtoF( zBuf, ref r, sqlite3Strlen30( zBuf ), SQLITE_UTF8 ); //sqlite3_free( ref zBuf ); } sqlite3_result_double( context, r ); }