Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch experimental-namelist Excluding Merge-Ins
This is equivalent to a diff from c5ed5ebdf6 to f4229857a1
2017-07-07
| ||
14:54 | Fix an obsolete comment on the sqlite3_namelist() function implementation. (Closed-Leaf check-in: f4229857a1 user: drh tags: experimental-namelist) | |
2017-07-06
| ||
22:43 | Small adjustment to main.mk that facilitates giving non-standard compile-time options to the shell. (check-in: 7c7d53a9bb user: drh tags: trunk) | |
22:40 | Always load the schema before starting tab-completion. (check-in: 907fd3aab6 user: drh tags: experimental-namelist) | |
17:36 | Initial implementation of a highly experimental interface for listing all keywords and symbolic names for an SQLite database connection. (check-in: 04ef6783a5 user: drh tags: experimental-namelist) | |
16:33 | Change the (machine-generated) keywordhash.h file to increase the scope of the tables used for keyword matching, so that the tables are accessible to functions other then keywordCode(). (check-in: c5ed5ebdf6 user: drh tags: trunk) | |
13:51 | More compact implementation of the typeof() SQL function. (check-in: efb4aab0ca user: drh tags: trunk) | |
Changes to main.mk.
︙ | ︙ | |||
470 471 472 473 474 475 476 | # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # | | | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5 SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 DBFUZZ_OPT = |
︙ | ︙ |
Changes to src/hash.h.
︙ | ︙ | |||
87 88 89 90 91 92 93 | #define sqliteHashData(E) ((E)->data) /* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ | | | 87 88 89 90 91 92 93 94 95 96 | #define sqliteHashData(E) ((E)->data) /* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ /* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ /* ** Number of entries in a hash table */ #define sqliteHashCount(H) ((H)->count) #endif /* SQLITE_HASH_H */ |
Changes to src/shell.c.
︙ | ︙ | |||
3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 | sha3QueryFunc, 0, 0); sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); } } /* ** Do C-language style dequoting. ** ** \a -> alarm ** \b -> backspace ** \t -> tab ** \n -> newline | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 | sha3QueryFunc, 0, 0); sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); } } #if HAVE_READLINE || HAVE_EDITLINE /* ** Readline completion callbacks */ static char *readline_completion_generator(const char *text, int state){ static char **azCompletions = 0; static int iCompletion = 0; char *zRet; if( state==0 ){ sqlite3_free(azCompletions); sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ azCompletions = sqlite3_namelist(globalDb, text, -1, 0); iCompletion = 0; } zRet = azCompletions[iCompletion++]; if( zRet==0 ){ sqlite3_free(azCompletions); azCompletions = 0; }else{ zRet = strdup(zRet); } return zRet; } static char **readline_completion(const char *zText, int iStart, int iEnd){ rl_attempted_completion_over = 1; return rl_completion_matches(zText, readline_completion_generator); } #elif HAVE_LINENOISE /* ** Linenoise completion callback */ static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ int nLine = (int)strlen(zLine); int i, n, iStart; char **az; char zBuf[1000]; if( nLine>sizeof(zBuf)-30 ) return; if( zLine[0]=='.' ) return; for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){} if( i==nLine-1 ) return; iStart = i+1; sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ az = sqlite3_namelist(globalDb, &zLine[iStart], -1, &n); if( n>0 ){ qsort(az, n, sizeof(az[0]),(int(*)(const void*,const void*))sqlite3_stricmp); memcpy(zBuf, zLine, iStart); for(i=0; az[i]; i++){ n = (int)strlen(az[i]); if( iStart+n+1 >= sizeof(zBuf) ) continue; memcpy(zBuf+iStart, az[i], n+1); linenoiseAddCompletion(lc, zBuf); } } sqlite3_free(az); } #endif /* ** Do C-language style dequoting. ** ** \a -> alarm ** \b -> backspace ** \t -> tab ** \n -> newline |
︙ | ︙ | |||
7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 | if( zHome ){ nHistory = strlen30(zHome) + 20; if( (zHistory = malloc(nHistory))!=0 ){ sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); } } if( zHistory ){ shell_read_history(zHistory); } rc = process_input(&data, 0); if( zHistory ){ shell_stifle_history(100); shell_write_history(zHistory); free(zHistory); } }else{ | > > > > > | 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 | if( zHome ){ nHistory = strlen30(zHome) + 20; if( (zHistory = malloc(nHistory))!=0 ){ sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); } } if( zHistory ){ shell_read_history(zHistory); } #if HAVE_READLINE || HAVE_EDITLINE rl_attempted_completion_function = readline_completion; #elif HAVE_LINENOISE linenoiseSetCompletionCallback(linenoise_completion); #endif rc = process_input(&data, 0); if( zHistory ){ shell_stifle_history(100); shell_write_history(zHistory); free(zHistory); } }else{ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 | ); int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); int sqlite3_preupdate_count(sqlite3 *); int sqlite3_preupdate_depth(sqlite3 *); int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); #endif /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error ** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 | ); int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **); int sqlite3_preupdate_count(sqlite3 *); int sqlite3_preupdate_depth(sqlite3 *); int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **); #endif /* ** CAPI3REF: List Of Symbolic Names ** ** ^The sqlite3_namelist(D,P,F,N) interface returns a list of symbolic names ** and keywords that might appear in valid SQL statements for [connection] ** D and that all begin with the prefix P. ^The F parameter is a bitmask ** that determines the kinds of symbolic names and keywords that are found ** in the list. ^Matching against the prefix P is performed using ** [sqlite3_strnicmp()] and is thus case insensitive for ASCII characters. ** ^If the pointer N is not NULL, then the number of matching names is ** stored in *N. ** ** ^The value returned by sqlite3_namelist() is stored in memory obtained ** from [sqlite3_malloc()] and must be released by the caller using ** [sqlite3_free()]. ^The sqlite3_namelist() interface returns NULL if a ** memory allocation error occurs. ** ** ^Elements of the list are unique but are in no particular order. ** ** This interface is intended to facilitate tab-completion for interactive ** interfaces for SQLite. */ char **sqlite3_namelist(sqlite3 *db, const char *zPrefix, int typeMask, int*); /* ** CAPI3REF: Symbolic Name Typemask Values ** ** ^These bitmask values are used to determine the kinds of symbolic names ** and keywords that are returned by [sqlite3_namelist()]. The third ** parameter to [sqlite3_namelist()] should be an OR-ed combination of ** one or more of the following value. */ #define SQLITE_NAMETYPE_KEYWORD 0x0001 #define SQLITE_NAMETYPE_SCHEMA 0x0002 #define SQLITE_NAMETYPE_TABLE 0x0004 #define SQLITE_NAMETYPE_INDEX 0x0008 #define SQLITE_NAMETYPE_TRIGGER 0x0010 #define SQLITE_NAMETYPE_FUNCTION 0x0020 #define SQLITE_NAMETYPE_MODULE 0x0040 #define SQLITE_NAMETYPE_COLLATION 0x0080 #define SQLITE_NAMETYPE_COLUMN 0x0100 /* ** CAPI3REF: Low-level system error code ** ** ^Attempt to return the underlying operating system error code or error ** number that caused the most recent I/O error or failure to open a file. ** The return value is OS-dependent. For example, on unix systems, after ** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
1846 1847 1848 1849 1850 1851 1852 | static const char *DB_strs[] = { "authorizer", "backup", "busy", "cache", "changes", "close", "collate", "collation_needed", "commit_hook", "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "incrblob", "interrupt", | | | | | | | | < | | | | | | | | 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | static const char *DB_strs[] = { "authorizer", "backup", "busy", "cache", "changes", "close", "collate", "collation_needed", "commit_hook", "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "incrblob", "interrupt", "last_insert_rowid", "namelist", "nullvalue", "onecolumn", "preupdate", "profile", "progress", "rekey", "restore", "rollback_hook", "status", "timeout", "total_changes", "trace", "trace_v2", "transaction", "unlock_notify", "update_hook", "version", "wal_hook", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, DB_NAMELIST, DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, DB_WAL_HOOK, }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } |
︙ | ︙ | |||
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 | ** Interrupt the execution of the inner-most SQL interpreter. This ** causes the SQL statement to return an error of SQLITE_INTERRUPT. */ case DB_INTERRUPT: { sqlite3_interrupt(pDb->db); break; } /* ** $db nullvalue ?STRING? ** ** Change text used when a NULL comes back from the database. If ?STRING? ** is not present, then the current string used for NULL is returned. ** If STRING is present, then STRING is returned. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 | ** Interrupt the execution of the inner-most SQL interpreter. This ** causes the SQL statement to return an error of SQLITE_INTERRUPT. */ case DB_INTERRUPT: { sqlite3_interrupt(pDb->db); break; } /* ** $db namelist PREFIX MASK */ case DB_NAMELIST: { const char *zPrefix; int mask; char **azList; int nList, i; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "PREFIX MASK"); return TCL_ERROR; } zPrefix = Tcl_GetString(objv[2]); if( Tcl_GetIntFromObj(interp, objv[3], &mask) ) return TCL_ERROR; azList = sqlite3_namelist(pDb->db, zPrefix, mask, &nList); if( azList ){ Tcl_Obj *pList = Tcl_NewListObj(nList, 0); for(i=0; azList[i]; i++){ Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(azList[i],-1)); } assert( i==nList ); sqlite3_free(azList); Tcl_SetObjResult(interp, pList); } break; } /* ** $db nullvalue ?STRING? ** ** Change text used when a NULL comes back from the database. If ?STRING? ** is not present, then the current string used for NULL is returned. ** If STRING is present, then STRING is returned. |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
610 611 612 613 614 615 616 | Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } /* An instance of the following object is used to accumulate a list ** of names for the sqlite3_namelist() interface */ struct NameAccum { Hash x; /* Hash table of all names */ const char *zPrefix; /* All names must start with this prefix */ int nPrefix; /* Size of the prefix in bytes */ }; /* ** Examine zName to see if it belongs on the list (if it has a matching ** prefix) and add it to the list if it belongs. nName is the length ** of the name in bytes, or -1 if zName is zero-terminated. */ static void addName(struct NameAccum *p, const char *zName, int nName){ char *zCopy; char *zOld; if( nName<0 ) nName = sqlite3Strlen30(zName); if( nName<p->nPrefix ) return; if( sqlite3StrNICmp(p->zPrefix, zName, p->nPrefix)!=0 ) return; zCopy = sqlite3_mprintf("%.*s", nName, zName); zOld = sqlite3HashInsert(&p->x, zCopy, zCopy); sqlite3_free(zOld); } /* ** Return a list of text words or identifiers that might appear in an ** SQL statement. The typeMask parameter is a bitmask that determines ** specifically what kinds of names should be returned. All names ** returned must begin with zPrefix. ** ** The returned list is from a single memory allocation. The caller owns ** the allocation and should release it using sqlite3_free() when it has ** finished using the list. ** ** The returned list is an array of pointers to strings. The list is ** terminated by a single NULL pointer. */ char **sqlite3_namelist( sqlite3 *db, /* Database from which to extract names */ const char *zPrefix, /* Only extract names matching this prefix */ int typeMask, /* Mask of the types of names to extract */ int *pCount /* Write the number of names here */ ){ struct NameAccum x; int i, n, nEntry; HashElem *j; char **azAns; char *zFree; x.zPrefix = zPrefix; x.nPrefix = sqlite3Strlen30(zPrefix); sqlite3HashInit(&x.x); if( typeMask & SQLITE_NAMETYPE_KEYWORD ){ for(i=0; i<ArraySize(aKWOffset); i++){ addName(&x, zKWText + aKWOffset[i], aKWLen[i]); } } if( typeMask & SQLITE_NAMETYPE_FUNCTION ){ for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ FuncDef *p; for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){ addName(&x, p->zName, -1); } } for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){ FuncDef *p = (FuncDef*)sqliteHashData(j); addName(&x, p->zName, -1); } } if( typeMask & SQLITE_NAMETYPE_COLLATION ){ for(j=sqliteHashFirst(&db->aCollSeq); j; j=sqliteHashNext(j)){ CollSeq *p = (CollSeq*)sqliteHashData(j); addName(&x, p->zName, -1); } } if( typeMask & SQLITE_NAMETYPE_MODULE ){ for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){ Module *p = (Module*)sqliteHashData(j); addName(&x, p->zName, -1); } } if( typeMask & (SQLITE_NAMETYPE_SCHEMA| SQLITE_NAMETYPE_TABLE| SQLITE_NAMETYPE_INDEX| SQLITE_NAMETYPE_TRIGGER| SQLITE_NAMETYPE_COLUMN) ){ int iDb; for(iDb=0; iDb<db->nDb; iDb++){ Db *pDb = &db->aDb[iDb]; if( typeMask & SQLITE_NAMETYPE_SCHEMA ){ addName(&x, pDb->zDbSName, -1); } if( typeMask & (SQLITE_NAMETYPE_TABLE|SQLITE_NAMETYPE_COLUMN) ){ for(j=sqliteHashFirst(&pDb->pSchema->tblHash); j; j=sqliteHashNext(j)){ Table *p = (Table*)sqliteHashData(j); if( typeMask & SQLITE_NAMETYPE_TABLE ){ addName(&x, p->zName, -1); } if( typeMask & SQLITE_NAMETYPE_COLUMN ){ int k; for(k=0; k<p->nCol; k++){ addName(&x, p->aCol[k].zName, -1); } } } } if( typeMask & SQLITE_NAMETYPE_INDEX ){ for(j=sqliteHashFirst(&pDb->pSchema->idxHash); j; j=sqliteHashNext(j)){ Index *p = (Index*)sqliteHashData(j); addName(&x, p->zName, -1); } } if( typeMask & SQLITE_NAMETYPE_TRIGGER ){ for(j=sqliteHashFirst(&pDb->pSchema->trigHash); j; j=sqliteHashNext(j)){ Trigger *p = (Trigger*)sqliteHashData(j); addName(&x, p->zName, -1); } } } if( typeMask & SQLITE_NAMETYPE_COLUMN ){ addName(&x, "rowid", -1); } } nEntry = sqliteHashCount(&x.x); if( pCount ) *pCount = nEntry; n = 0; for(j=sqliteHashFirst(&x.x); j; j=sqliteHashNext(j)){ n += sqlite3Strlen30((const char*)sqliteHashData(j)); } zFree = sqlite3_malloc( (nEntry+1)*sizeof(char*) + n + nEntry ); azAns = (char**)zFree; if( zFree ){ memset(zFree, 0, (nEntry+1)*sizeof(char*) + n + nEntry ); zFree += (nEntry+1)*sizeof(char*); for(i=0, j=sqliteHashFirst(&x.x); j; i++, j=sqliteHashNext(j)){ const char *zName = (const char*)sqliteHashData(j); azAns[i] = zFree; n = sqlite3Strlen30(zName); memcpy(zFree, zName, n+1); zFree += n+1; } } for(j=sqliteHashFirst(&x.x); j; j=sqliteHashNext(j)){ sqlite3_free(sqliteHashData(j)); } sqlite3HashClear(&x.x); return azAns; } |