📄 func.c
字号:
sqlite3_result_int(context, sqlite3_total_changes(db));}/*** A structure defining how to do GLOB-style comparisons.*/struct compareInfo { u8 matchAll; u8 matchOne; u8 matchSet; u8 noCase;};/*** For LIKE and GLOB matching on EBCDIC machines, assume that every** character is exactly one byte in size. Also, all characters are** able to participate in upper-case-to-lower-case mappings in EBCDIC** whereas only characters less than 0x80 do in ASCII.*/#if defined(SQLITE_EBCDIC)# define sqlite3Utf8Read(A,B,C) (*(A++))# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]#else# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; }#endifstatic const struct compareInfo globInfo = { '*', '?', '[', 0 };/* The correct SQL-92 behavior is for the LIKE operator to ignore** case. Thus 'a' LIKE 'A' would be true. */static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator** is case sensitive causing 'a' LIKE 'A' to be false */static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };/*** Compare two UTF-8 strings for equality where the first string can** potentially be a "glob" expression. Return true (1) if they** are the same and false (0) if they are different.**** Globbing rules:**** '*' Matches any sequence of zero or more characters.**** '?' Matches exactly one character.**** [...] Matches one character from the enclosed list of** characters.**** [^...] Matches one character not in the enclosed list.**** With the [...] and [^...] matching, a ']' character can be included** in the list by making it the first character after '[' or '^'. A** range of characters can be specified using '-'. Example:** "[a-z]" matches any single lower-case letter. To match a '-', make** it the last character in the list.**** This routine is usually quick, but can be N**2 in the worst case.**** Hints: to match '*' or '?', put them in "[]". Like this:**** abc[*]xyz Matches "abc*xyz" only*/static int patternCompare( const u8 *zPattern, /* The glob pattern */ const u8 *zString, /* The string to compare against the glob */ const struct compareInfo *pInfo, /* Information about how to do the compare */ const int esc /* The escape character */){ int c, c2; int invert; int seen; u8 matchOne = pInfo->matchOne; u8 matchAll = pInfo->matchAll; u8 matchSet = pInfo->matchSet; u8 noCase = pInfo->noCase; int prevEscape = 0; /* True if the previous character was 'escape' */ while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){ if( !prevEscape && c==matchAll ){ while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll || c == matchOne ){ if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){ return 0; } } if( c==0 ){ return 1; }else if( c==esc ){ c = sqlite3Utf8Read(zPattern, 0, &zPattern); if( c==0 ){ return 0; } }else if( c==matchSet ){ assert( esc==0 ); /* This is GLOB, not LIKE */ assert( matchSet<0x80 ); /* '[' is a single-byte character */ while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ SQLITE_SKIP_UTF8(zString); } return *zString!=0; } while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){ if( noCase ){ GlogUpperToLower(c2); GlogUpperToLower(c); while( c2 != 0 && c2 != c ){ c2 = sqlite3Utf8Read(zString, 0, &zString); GlogUpperToLower(c2); } }else{ while( c2 != 0 && c2 != c ){ c2 = sqlite3Utf8Read(zString, 0, &zString); } } if( c2==0 ) return 0; if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; } return 0; }else if( !prevEscape && c==matchOne ){ if( sqlite3Utf8Read(zString, 0, &zString)==0 ){ return 0; } }else if( c==matchSet ){ int prior_c = 0; assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ seen = 0; invert = 0; c = sqlite3Utf8Read(zString, 0, &zString); if( c==0 ) return 0; c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); if( c2=='^' ){ invert = 1; c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); } if( c2==']' ){ if( c==']' ) seen = 1; c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); } while( c2 && c2!=']' ){ if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); if( c>=prior_c && c<=c2 ) seen = 1; prior_c = 0; }else{ if( c==c2 ){ seen = 1; } prior_c = c2; } c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); } if( c2==0 || (seen ^ invert)==0 ){ return 0; } }else if( esc==c && !prevEscape ){ prevEscape = 1; }else{ c2 = sqlite3Utf8Read(zString, 0, &zString); if( noCase ){ GlogUpperToLower(c); GlogUpperToLower(c2); } if( c!=c2 ){ return 0; } 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, *zB; int escape = 0; 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(). */ if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); return; } 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. */ const unsigned char *zEsc = sqlite3_value_text(argv[2]); if( zEsc==0 ) return; if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ sqlite3_result_error(context, "ESCAPE expression must be a single character", -1); return; } escape = sqlite3Utf8Read(zEsc, 0, &zEsc); } if( zA && zB ){ struct compareInfo *pInfo = sqlite3_user_data(context);#ifdef SQLITE_TEST sqlite3_like_count++;#endif sqlite3_result_int(context, patternCompare(zB, zA, 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; char const *zBlob = sqlite3_value_blob(argv[0]); int nBlob = sqlite3_value_bytes(argv[0]); assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ if( 2*nBlob+4>SQLITE_MAX_LENGTH ){ sqlite3_result_error_toobig(context); return; } zText = (char *)contextMalloc(context, (2*nBlob)+4); if( zText ){ 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); sqlite3_free(zText); } break; } case SQLITE_TEXT: { int i,j; u64 n; const unsigned char *zArg = sqlite3_value_text(argv[0]); char *z; if( zArg==0 ) return; for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } if( i+n+3>SQLITE_MAX_LENGTH ){ sqlite3_result_error_toobig(context); return; } z = contextMalloc(context, i+n+3); if( z ){ 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, sqlite3_free); } } }}/*** 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 ); pBlob = sqlite3_value_blob(argv[0]); n = sqlite3_value_bytes(argv[0]); if( n*2+1>SQLITE_MAX_LENGTH ){ sqlite3_result_error_toobig(context); return; } assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ z = zHex = contextMalloc(context, n*2 + 1); if( zHex ){ 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 zeroblob(N) function returns a zero-filled blob of size N bytes.*/static void zeroblobFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ i64 n; assert( argc==1 ); n = sqlite3_value_int64(argv[0]); if( n>SQLITE_MAX_LENGTH ){ sqlite3_result_error_toobig(context); }else{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -