📄 func.c
字号:
if( c==0 ) return 0; c2 = *++zPattern; if( c2=='^' ){ invert = 1; c2 = *++zPattern; } if( c2==']' ){ if( c==']' ) seen = 1; c2 = *++zPattern; } while( (c2 = sqliteCharVal(zPattern))!=0 && c2!=']' ){ if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ zPattern++; c2 = sqliteCharVal(zPattern); if( c>=prior_c && c<=c2 ) seen = 1; prior_c = 0; }else if( c==c2 ){ seen = 1; prior_c = c2; }else{ prior_c = c2; } sqliteNextChar(zPattern); } if( c2==0 || (seen ^ invert)==0 ) return 0; sqliteNextChar(zString); zPattern++; }else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){ prevEscape = 1; sqliteNextChar(zPattern); }else{ if( noCase ){ if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0; }else{ if( c != *zString ) return 0; } zPattern++; zString++; prevEscape = 0; } } return *zString==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.*/#ifdef SQLITE_TESTint sqlite3_like_count = 0;#endif/*** 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){ const unsigned char *zA = sqlite3_value_text(argv[0]); const unsigned char *zB = sqlite3_value_text(argv[1]); int escape = 0; if( argc==3 ){ /* The escape character string must consist of a single UTF-8 character. ** Otherwise, return an error. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( sqlite3utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3ReadUtf8(zEsc); } if( zA && zB ){ struct compareInfo *pInfo = sqlite3_user_data(context);#ifdef SQLITE_TEST sqlite3_like_count++;#endif sqlite3_result_int(context, patternCompare(zA, zB, pInfo, escape)); }}/*** 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 argc, sqlite3_value **argv){ CollSeq *pColl = sqlite3GetFuncCollSeq(context); if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ sqlite3_result_value(context, argv[0]); }}/*** Implementation of the VERSION(*) function. The result is the version** of the SQLite library that is running.*/static void versionFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);}/* Array for converting from half-bytes (nybbles) into ASCII hex** digits. */static const char hexdigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };/*** 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){ if( argc<1 ) return; switch( sqlite3_value_type(argv[0]) ){ case SQLITE_NULL: { sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_value(context, argv[0]); break; } case SQLITE_BLOB: { char *zText = 0; int nBlob = sqlite3_value_bytes(argv[0]); char const *zBlob = sqlite3_value_blob(argv[0]); zText = (char *)sqliteMalloc((2*nBlob)+4); if( !zText ){ sqlite3_result_error(context, "out of memory", -1); }else{ int i; for(i=0; i<nBlob; i++){ zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F]; zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; } zText[(nBlob*2)+2] = '\''; zText[(nBlob*2)+3] = '\0'; zText[0] = 'X'; zText[1] = '\''; sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); sqliteFree(zText); } break; } case SQLITE_TEXT: { int i,j,n; const unsigned char *zArg = sqlite3_value_text(argv[0]); char *z; for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } z = sqliteMalloc( i+n+3 ); if( z==0 ) return; z[0] = '\''; for(i=0, j=1; zArg[i]; i++){ z[j++] = zArg[i]; if( zArg[i]=='\'' ){ z[j++] = '\''; } } z[j++] = '\''; z[j] = 0; sqlite3_result_text(context, z, j, SQLITE_TRANSIENT); sqliteFree(z); } }}/*** 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; const unsigned char *pBlob; char *zHex, *z; assert( argc==1 ); n = sqlite3_value_bytes(argv[0]); pBlob = sqlite3_value_blob(argv[0]); z = zHex = sqlite3_malloc(n*2 + 1); if( zHex==0 ) return; for(i=0; i<n; i++, pBlob++){ unsigned char c = *pBlob; *(z++) = hexdigits[(c>>4)&0xf]; *(z++) = hexdigits[c&0xf]; } *z = 0; sqlite3_result_text(context, zHex, n*2, sqlite3_free);}/*** 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){ const unsigned char *zStr; /* The input string A */ const unsigned char *zPattern; /* The pattern string B */ const unsigned char *zRep; /* The replacement string C */ unsigned char *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 */ assert( argc==3 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL || sqlite3_value_type(argv[2])==SQLITE_NULL ){ return; } zStr = sqlite3_value_text(argv[0]); nStr = sqlite3_value_bytes(argv[0]); zPattern = sqlite3_value_text(argv[1]); nPattern = sqlite3_value_bytes(argv[1]); zRep = sqlite3_value_text(argv[2]); nRep = sqlite3_value_bytes(argv[2]); if( nPattern>=nRep ){ nOut = nStr; }else{ nOut = (nStr/nPattern + 1)*nRep; } zOut = sqlite3_malloc(nOut+1); 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{ memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; } } memcpy(&zOut[j], &zStr[i], nStr-i); j += nStr - i; assert( j<=nOut ); zOut[j] = 0; sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);}/*** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.*/static void trimFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ const unsigned char *zIn; /* Input string */ const unsigned char *zCharSet; /* Set of characters to trim */ int nIn; /* Number of bytes in input */ int flags; int i; unsigned char cFirst, cNext; if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ return; } zIn = sqlite3_value_text(argv[0]); nIn = sqlite3_value_bytes(argv[0]); if( argc==1 ){ static const unsigned char zSpace[] = " "; zCharSet = zSpace; }else if( sqlite3_value_type(argv[1])==SQLITE_NULL ){ return; }else{ zCharSet = sqlite3_value_text(argv[1]); } cFirst = zCharSet[0]; if( cFirst ){ flags = (int)sqlite3_user_data(context); if( flags & 1 ){ for(; nIn>0; nIn--, zIn++){ if( cFirst==zIn[0] ) continue; for(i=1; zCharSet[i] && zCharSet[i]!=zIn[0]; i++){} if( zCharSet[i]==0 ) break; } } if( flags & 2 ){ for(; nIn>0; nIn--){ cNext = zIn[nIn-1]; if( cFirst==cNext ) continue; for(i=1; zCharSet[i] && zCharSet[i]!=cNext; i++){} if( zCharSet[i]==0 ) break; } } } sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);}#ifdef SQLITE_SOUNDEX/*** Compute the soundex encoding of a word.*/static void soundexFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ char zResult[8]; const u8 *zIn; int i, j; static const unsigned char iCode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, }; assert( argc==1 ); zIn = (u8*)sqlite3_value_text(argv[0]); if( zIn==0 ) zIn = (u8*)""; for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} if( zIn[i] ){ u8 prevcode = iCode[zIn[i]&0x7f]; zResult[0] = toupper(zIn[i]); for(j=1; j<4 && zIn[i]; i++){ int code = iCode[zIn[i]&0x7f]; if( code>0 ){ if( code!=prevcode ){ prevcode = code; zResult[j++] = code + '0'; } }else{ prevcode = 0; } } while( j<4 ){ zResult[j++] = '0'; } zResult[j] = 0; sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); }else{ sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); }}#endif#ifndef SQLITE_OMIT_LOAD_EXTENSION/*** A function that loads a shared-library extension then returns NULL.*/static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *zFile = (const char *)sqlite3_value_text(argv[0]); const char *zProc = 0; sqlite3 *db = sqlite3_user_data(context); char *zErrMsg = 0; if( argc==2 ){ zProc = (const char *)sqlite3_value_text(argv[1]); } if( sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ sqlite3_result_error(context, zErrMsg, -1); sqlite3_free(zErrMsg); }}#endif#ifdef SQLITE_TEST/*** This function generates a string of random characters. Used for** generating test data.*/static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ static const unsigned char zSrc[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" ".-!,:*^+=_|?/<> "; int iMin, iMax, n, r, i; unsigned char zBuf[1000]; if( argc>=1 ){ iMin = sqlite3_value_int(argv[0]); if( iMin<0 ) iMin = 0; if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; }else{ iMin = 1; } if( argc>=2 ){ iMax = sqlite3_value_int(argv[1]); if( iMax<iMin ) iMax = iMin; if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; }else{ iMax = 50; } n = iMin; if( iMax>iMin ){ sqlite3Randomness(sizeof(r), &r); r &= 0x7fffffff; n += r%(iMax + 1 - iMin); } assert( n<sizeof(zBuf) ); sqlite3Randomness(n, zBuf); for(i=0; i<n; i++){ zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)]; } zBuf[n] = 0; sqlite3_result_text(context, (char*)zBuf, n, SQLITE_TRANSIENT);}#endif /* SQLITE_TEST */#ifdef SQLITE_TEST/*** The following two SQL functions are used to test returning a text** result with a destructor. Function 'test_destructor' takes one argument** and returns the same argument interpreted as TEXT. A destructor is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -