Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add new interfaces for accessing the list of SQL keywords: sqlite3_keyword_count(), sqlite3_keyword_name(), sqlite3_keyword_check(). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
7dd34e3776fed90a49344d54a1b68bb5 |
User & Date: | drh 2018-04-25 19:02:48.148 |
Context
2018-04-26
| ||
08:56 | Update the "fuzz_malloc.test" script to print SQL statements in which OOM handling problems are found to stdout. (check-in: a956363cf6 user: dan tags: trunk) | |
2018-04-25
| ||
19:02 | Add new interfaces for accessing the list of SQL keywords: sqlite3_keyword_count(), sqlite3_keyword_name(), sqlite3_keyword_check(). (check-in: 7dd34e3776 user: drh tags: trunk) | |
17:10 | Add the new DO and NOTHING keywords to the keyword lists maintained by various extensions and auxiliary programs. (check-in: 77a98a0781 user: drh tags: trunk) | |
Changes
Changes to ext/misc/completion.c.
︙ | ︙ | |||
58 59 60 61 62 63 64 65 66 67 68 69 70 71 | struct completion_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3 *db; /* Database connection for this cursor */ int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */ char *zPrefix; /* The prefix for the word we want to complete */ char *zLine; /* The whole that we want to complete */ const char *zCurrentRow; /* Current output row */ sqlite3_stmt *pStmt; /* Current statement */ sqlite3_int64 iRowid; /* The rowid */ int ePhase; /* Current phase */ int j; /* inter-phase counter */ }; /* Values for ePhase: | > | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | struct completion_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3 *db; /* Database connection for this cursor */ int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */ char *zPrefix; /* The prefix for the word we want to complete */ char *zLine; /* The whole that we want to complete */ const char *zCurrentRow; /* Current output row */ int szRow; /* Length of the zCurrentRow string */ sqlite3_stmt *pStmt; /* Current statement */ sqlite3_int64 iRowid; /* The rowid */ int ePhase; /* Current phase */ int j; /* inter-phase counter */ }; /* Values for ePhase: |
︙ | ︙ | |||
170 171 172 173 174 175 176 | */ static int completionClose(sqlite3_vtab_cursor *cur){ completionCursorReset((completion_cursor*)cur); sqlite3_free(cur); return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | */ static int completionClose(sqlite3_vtab_cursor *cur){ completionCursorReset((completion_cursor*)cur); sqlite3_free(cur); return SQLITE_OK; } /* ** Advance a completion_cursor to its next row of output. ** ** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object ** record the current state of the scan. This routine sets ->zCurrentRow ** to the current row of output and then returns. If no more rows remain, ** then ->ePhase is set to COMPLETION_EOF which will signal the virtual |
︙ | ︙ | |||
219 220 221 222 223 224 225 | completion_cursor *pCur = (completion_cursor*)cur; int eNextPhase = 0; /* Next phase to try if current phase reaches end */ int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */ pCur->iRowid++; while( pCur->ePhase!=COMPLETION_EOF ){ switch( pCur->ePhase ){ case COMPLETION_KEYWORDS: { | | | | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | completion_cursor *pCur = (completion_cursor*)cur; int eNextPhase = 0; /* Next phase to try if current phase reaches end */ int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */ pCur->iRowid++; while( pCur->ePhase!=COMPLETION_EOF ){ switch( pCur->ePhase ){ case COMPLETION_KEYWORDS: { if( pCur->j >= sqlite3_keyword_count() ){ pCur->zCurrentRow = 0; pCur->ePhase = COMPLETION_DATABASES; }else{ sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); } iCol = -1; break; } case COMPLETION_DATABASES: { if( pCur->pStmt==0 ){ sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, |
︙ | ︙ | |||
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | if( iCol<0 ){ /* This case is when the phase presets zCurrentRow */ if( pCur->zCurrentRow==0 ) continue; }else{ if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ /* Extract the next row of content */ pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); }else{ /* When all rows are finished, advance to the next phase */ sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0; pCur->ePhase = eNextPhase; continue; } } if( pCur->nPrefix==0 ) break; | > > | > | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | if( iCol<0 ){ /* This case is when the phase presets zCurrentRow */ if( pCur->zCurrentRow==0 ) continue; }else{ if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ /* Extract the next row of content */ pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); }else{ /* When all rows are finished, advance to the next phase */ sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0; pCur->ePhase = eNextPhase; continue; } } if( pCur->nPrefix==0 ) break; if( pCur->nPrefix<=pCur->szRow && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){ break; } } return SQLITE_OK; } /* ** Return values of columns for the row at which the completion_cursor ** is currently pointing. */ static int completionColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ completion_cursor *pCur = (completion_cursor*)cur; switch( i ){ case COMPLETION_COLUMN_CANDIDATE: { sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); break; } case COMPLETION_COLUMN_PREFIX: { sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT); break; } case COMPLETION_COLUMN_WHOLELINE: { |
︙ | ︙ |
Changes to ext/misc/dbdump.c.
︙ | ︙ | |||
137 138 139 140 141 142 143 | ** because it contains non-alphanumeric characters, or because it is an ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | ** because it contains non-alphanumeric characters, or because it is an ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ int i; if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; for(i=0; zName[i]; i++){ if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; } return sqlite3_keyword_check(zName, i) ? '"' : 0; } /* ** Release memory previously allocated by tableColumnList(). */ static void freeColumnList(char **azCol){ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
3857 3858 3859 3860 3861 3862 3863 | */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); break; } | < < < < < < < < < < < < < < < < < < | 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 | */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); break; } /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** ** If parameter onoff is non-zero, configure the wrappers so that all ** subsequent calls to localtime() and variants fail. If onoff is zero, ** undo this setting. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
770 771 772 773 774 775 776 | ** because it contains non-alphanumeric characters, or because it is an ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 | ** because it contains non-alphanumeric characters, or because it is an ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ int i; if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; for(i=0; zName[i]; i++){ if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; } return sqlite3_keyword_check(zName, i) ? '"' : 0; } /* ** Construct a fake object name and column list to describe the structure ** of the view, virtual table, or table valued function zSchema.zName. */ static char *shellFakeSchema( |
︙ | ︙ | |||
7493 7494 7495 7496 7497 7498 7499 | { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, | < < < | 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 | { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, #ifdef YYCOVERAGE { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, |
︙ | ︙ | |||
7607 7608 7609 7610 7611 7612 7613 | if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; | < < < < < < < < < < < | 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 | if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 3; } break; case SQLITE_TESTCTRL_IMPOSTER: if( nArg==5 ){ rc2 = sqlite3_test_control(testctrl, p->db, azArg[2], integerValue(azArg[3]), integerValue(azArg[4])); isOk = 3; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7012 7013 7014 7015 7016 7017 7018 | #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 | #define SQLITE_TESTCTRL_FAULT_INSTALL 9 #define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 #define SQLITE_TESTCTRL_PENDING_BYTE 11 #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 #define SQLITE_TESTCTRL_BYTEORDER 22 #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking ** ** These routines provide access to the set of SQL language keywords ** recognized by SQLite. Applications can uses these routines to determine ** whether or not a specific identifier needs to be escaped (for example, ** by enclosing in double-quotes) so as not to confuse the parser. ** ** The sqlite3_keyword_count() interface returns the number of distinct ** keywords understood by SQLite. ** ** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and ** makes *Z point to that keyword expressed as UTF8 and writes the number ** of bytes in the keyword into *L. The string that *Z points to is not ** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns ** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z ** or L are NULL or invalid pointers then calls to ** sqlite3_keyword_name(N,Z,L) result in undefined behavior. ** ** The sqlite3_keyword_check(Z,L) interface checks to see whether or not ** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero ** if it is and zero if not. ** ** The parser used by SQLite is forgiving. It is often possible to use ** a keyword as an identifier as long as such use does not result in a ** parsing ambiguity. For example, the statement ** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and ** creates a new table named "BEGIN" with three columns named ** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid ** using keywords as identifiers. Common techniques used to avoid keyword ** name collisions include: ** <ul> ** <li> Put all indentifier names inside double-quotes. This is the official ** SQL way to escape identifier names. ** <li> Put identifier names inside [...]. This is not standard SQL, ** but it is what SQL Server does and so lots of programmers use this ** technique. ** <li> Begin every identifier with the letter "Z" as no SQL keywords start ** with "Z". ** <li> Include a digit somewhere in every identifier name. ** </ul> ** ** Note that the number of keywords understood by SQLite can depend on ** compile-time options. For example, "VACUUM" is not a keyword if ** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, ** new keywords may be added to future releases of SQLite. */ int sqlite3_keyword_count(void); int sqlite3_keyword_name(int,const char**,int*); int sqlite3_keyword_check(const char*,int); /* ** CAPI3REF: SQLite Runtime Status ** ** ^These interfaces are used to retrieve runtime status information ** about the performance of SQLite, and optionally to reset various ** highwater marks. ^The first argument is an integer code for ** the specific parameter to measure. ^(Recognized integer codes |
︙ | ︙ |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
613 614 615 616 617 618 619 620 621 622 | printf("}\n"); printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n"); printf(" int id = TK_ID;\n"); printf(" keywordCode((char*)z, n, &id);\n"); printf(" return id;\n"); printf("}\n"); printf("#define SQLITE_N_KEYWORD %d\n", nKeyword); return 0; } | > > > > > > > > > > | 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | printf("}\n"); printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n"); printf(" int id = TK_ID;\n"); printf(" keywordCode((char*)z, n, &id);\n"); printf(" return id;\n"); printf("}\n"); printf("#define SQLITE_N_KEYWORD %d\n", nKeyword); printf("int sqlite3_keyword_name(int i,const char **pzName,int *pnName){\n"); printf(" if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;\n"); printf(" *pzName = zKWText + aKWOffset[i];\n"); printf(" *pnName = aKWLen[i];\n"); printf(" return SQLITE_OK;\n"); printf("}\n"); printf("int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; }\n"); printf("int sqlite3_keyword_check(const char *zName, int nName){\n"); printf(" return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName);\n"); printf("}\n"); return 0; } |
Changes to tool/sqldiff.c.
︙ | ︙ | |||
130 131 132 133 134 135 136 | ** necessary to allow the string to be used with %s. ** ** Space to hold the returned string is obtained from sqlite3_malloc(). The ** caller is responsible for ensuring this space is freed when no longer ** needed. */ static char *safeId(const char *zId){ | < < < < < < < < < < < < < < < < < < < < < < | > > | < < < < < < < < < < | < | | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | ** necessary to allow the string to be used with %s. ** ** Space to hold the returned string is obtained from sqlite3_malloc(). The ** caller is responsible for ensuring this space is freed when no longer ** needed. */ static char *safeId(const char *zId){ int i, x; char c; if( zId[0]==0 ) return sqlite3_mprintf("\"\""); for(i=x=0; (c = zId[i])!=0; i++){ if( !isalpha(c) && c!='_' ){ if( i>0 && isdigit(c) ){ x++; }else{ return sqlite3_mprintf("\"%w\"", zId); } } } if( x || !sqlite3_keyword_check(zId,i) ){ return sqlite3_mprintf("%s", zId); } return sqlite3_mprintf("\"%w\"", zId); } /* ** Prepare a new SQL statement. Print an error and abort if anything ** goes wrong. */ static sqlite3_stmt *db_vprepare(const char *zFormat, va_list ap){ |
︙ | ︙ |