Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Change the sqlite4_exec() function to pass protected sqlite4_value objects to the callback instead of an array of nul-terminated strings. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bbf3a54dcf2046c7b3d07628b7345b44 |
User & Date: | dan 2013-05-10 18:42:36.296 |
Context
2013-05-10
| ||
19:19 | Change sqlite4_prepare() to return the number of bytes read from the input SQL script via an output variable (instead of returning a pointer to the next SQL statement within the buffer). check-in: 79197d57b4 user: dan tags: trunk | |
18:42 | Change the sqlite4_exec() function to pass protected sqlite4_value objects to the callback instead of an array of nul-terminated strings. check-in: bbf3a54dcf user: dan tags: trunk | |
2013-05-09
| ||
19:47 | Add an "unsigned int flags" parameter to sqlite4_close(). Currently unused. check-in: 95275bb370 user: dan tags: trunk | |
Changes
Changes to src/legacy.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | /* ** Execute SQL code. Return one of the SQLITE4_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result | | | | | | < < | > > > > | > | > | > < > | < < < | < < | < > | > > > > > | | | | | < < | < < < < < < < | | | | < > > | > > | < < | | | | < < | | < > | < | | < < | | | | | > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | /* ** Execute SQL code. Return one of the SQLITE4_ success/failure ** codes. Also write an error message into memory obtained from ** malloc() and make *pzErrMsg point to that message. ** ** If the SQL is a query, then for each row in the query result ** the xCall() function is called. pArg becomes the first ** argument to xCall(). If xCall=NULL then no callback ** is invoked, even for queries. */ int sqlite4_exec( sqlite4 *db, /* The database on which the SQL executes */ const char *zSql, /* The SQL to be executed */ int (*xCall)(void*,int,sqlite4_value**,const char**), /* Callback function */ void *pArg, /* First argument to xCall() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE4_OK; /* Return code */ const char *zLeftover; /* Tail of unprocessed SQL */ int nRetry = 0; /* Number of retry attempts */ int bAbort = 0; /* Set to true if callback returns non-zero */ if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT; if( zSql==0 ) zSql = ""; sqlite4_mutex_enter(db->mutex); sqlite4Error(db, SQLITE4_OK, 0); /* Loop until we run out of SQL to execute, or the callback function ** returns non-zero, or an error occurs. */ while( zSql[0] && bAbort==0 && (rc==SQLITE4_OK || (rc==SQLITE4_SCHEMA && (++nRetry)<2)) ){ int nCol; /* Number of returned columns */ sqlite4_stmt *pStmt = 0; /* The current SQL statement */ const char **azCol = 0; /* Names of result columns */ sqlite4_value **apVal = 0; /* Row of value objects */ pStmt = 0; rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover); assert( rc==SQLITE4_OK || pStmt==0 ); if( rc!=SQLITE4_OK ){ continue; } if( !pStmt ){ /* this happens for a comment or white-space */ zSql = zLeftover; continue; } nCol = sqlite4_column_count(pStmt); do { /* Step the statement. Then invoke the callback function if required */ rc = sqlite4_step(pStmt); if( xCall && SQLITE4_ROW==rc ){ if( azCol==0 ){ int nAlloc; /* Bytes of space to allocate */ nAlloc = (sizeof(char *) + sizeof(sqlite4_value *)) * nCol; azCol = (const char **)sqlite4DbMallocZero(db, nAlloc); if( azCol ){ int i; /* Used to iterate through result columns */ apVal = (sqlite4_value **)&azCol[nCol]; for(i=0; i<nCol; i++){ azCol[i] = sqlite4_column_name(pStmt, i); /* sqlite4VdbeSetColName() installs column names as UTF8 ** strings so there is no way for column_name() to fail. */ assert( azCol[i]!=0 ); } } } if( azCol ){ int i; /* Used to iterate through result columns */ for(i=0; i<nCol; i++){ apVal[i] = sqlite4ColumnValue(pStmt, i); assert( apVal[i]!=0 ); } bAbort = xCall(pArg, nCol, apVal, azCol); } } if( bAbort || rc!=SQLITE4_ROW ){ rc = sqlite4VdbeFinalize((Vdbe *)pStmt); pStmt = 0; if( rc!=SQLITE4_SCHEMA ){ nRetry = 0; zSql = zLeftover; while( sqlite4Isspace(zSql[0]) ) zSql++; } assert( rc!=SQLITE4_ROW ); } }while( rc==SQLITE4_ROW ); sqlite4DbFree(db, azCol); } if( bAbort ) rc = SQLITE4_ABORT; rc = sqlite4ApiExit(db, rc); if( pzErrMsg ){ if( rc!=SQLITE4_OK ){ *pzErrMsg = sqlite4DbStrDup(0, sqlite4_errmsg(db)); if( 0==*pzErrMsg ){ rc = SQLITE4_NOMEM; sqlite4Error(db, SQLITE4_NOMEM, 0); } }else{ *pzErrMsg = 0; } } sqlite4_mutex_leave(db->mutex); return rc; } |
Changes to src/prepare.c.
︙ | ︙ | |||
34 35 36 37 38 39 40 | "%s - %s", *pData->pzErrMsg, zExtra); } } pData->rc = db->mallocFailed ? SQLITE4_NOMEM : SQLITE4_CORRUPT_BKPT; } /* | < < | < < < < < < < | | > > > > < < > > | < < < < | | < | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | "%s - %s", *pData->pzErrMsg, zExtra); } } pData->rc = db->mallocFailed ? SQLITE4_NOMEM : SQLITE4_CORRUPT_BKPT; } /* ** Create an in-memory schema object. */ static int initCallback( InitData *pData, /* Schema initialization context */ const char *zObj, /* Name of object being created */ int iRoot, /* Root page number. Zero for trigger/view */ const char *zSql /* Text of SQL CREATE statement */ ){ sqlite4 *db = pData->db; int iDb = pData->iDb; assert( sqlite4_mutex_held(db->mutex) ); assert( iDb>=0 && iDb<db->nDb ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ corruptSchema(pData, zObj, 0); return 1; } if( zSql && zSql[0] ){ /* Call the parser to process a CREATE TABLE, INDEX or VIEW. ** But because db->init.busy is set to 1, no VDBE code is generated ** or executed. All the parser does is build the internal data ** structures that describe the table, index, or view. */ int rc; sqlite4_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite4_prepare() */ assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = iRoot; db->init.orphanTrigger = 0; TESTONLY(rcp = ) sqlite4_prepare(db, zSql, -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = 0; if( SQLITE4_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ pData->rc = rc; if( rc==SQLITE4_NOMEM ){ db->mallocFailed = 1; }else if( rc!=SQLITE4_INTERRUPT && (rc&0xFF)!=SQLITE4_LOCKED ){ corruptSchema(pData, zObj, sqlite4_errmsg(db)); } } } sqlite4_finalize(pStmt); }else if( zObj==0 ){ corruptSchema(pData, 0, 0); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ Index *pIndex; pIndex = sqlite4FindIndex(db, zObj, db->aDb[iDb].zName); if( pIndex==0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. */ /* Do Nothing */; }else if( iRoot==0 ){ corruptSchema(pData, zObj, "invalid rootpage"); }else{ pIndex->tnum = iRoot; } } return 0; } /* ** This is the callback routine for the code that initializes the ** database. See sqlite4Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** ** argv[0] = name of thing being created ** argv[1] = root page number for table or index. 0 for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** */ int sqlite4InitCallback( void *pInit, int nVal, sqlite4_value **apVal, const char **azCol ){ InitData *pData = (InitData*)pInit; sqlite4 *db = pData->db; int iDb = pData->iDb; UNUSED_PARAMETER2(azCol, nVal); assert( nVal==3 ); assert( iDb>=0 && iDb<db->nDb ); assert( sqlite4_mutex_held(db->mutex) ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ corruptSchema(pData, sqlite4_value_text(apVal[0], 0), 0); }else if( apVal ){ if( sqlite4_value_type(apVal[1])==SQLITE4_NULL ){ corruptSchema(pData, sqlite4_value_text(apVal[0], 0), 0); }else{ initCallback(pData, sqlite4_value_text(apVal[0], 0), /* Object name */ sqlite4_value_int(apVal[1]), /* Root page number */ sqlite4_value_text(apVal[2], 0) /* Text of CREATE statement */ ); } } return 0; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE4_ error codes to ** indicate success or failure. */ static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){ int rc; Table *pTab; Db *pDb; InitData initData; char const *zMasterSchema; char const *zMasterName; int openedTransaction = 0; /* ** The master database table has a structure like this |
︙ | ︙ | |||
179 180 181 182 183 184 185 | zMasterSchema = temp_master_schema; }else{ zMasterSchema = master_schema; } zMasterName = SCHEMA_TABLE(iDb); /* Construct the schema tables. */ | < < < < | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | zMasterSchema = temp_master_schema; }else{ zMasterSchema = master_schema; } zMasterName = SCHEMA_TABLE(iDb); /* Construct the schema tables. */ initData.db = db; initData.iDb = iDb; initData.rc = SQLITE4_OK; initData.pzErrMsg = pzErrMsg; initCallback(&initData, zMasterName, 1, zMasterSchema); if( initData.rc ){ rc = initData.rc; goto error_out; } pTab = sqlite4FindTable(db, zMasterName, db->aDb[iDb].zName); if( ALWAYS(pTab) ){ pTab->tabFlags |= TF_Readonly; |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
271 272 273 274 275 276 277 | z = sqlite4_vmprintf(0, zFormat, ap); va_end(ap); fprintf(iotrace, "%s", z); sqlite4_free(0, z); } #endif | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | z = sqlite4_vmprintf(0, zFormat, ap); va_end(ap); fprintf(iotrace, "%s", z); sqlite4_free(0, z); } #endif /* ** A global char* and an SQL function to access its current value ** from within an SQL statement. This program used to use the ** sqlite_exec_printf() API to substitue a string into an SQL statement. ** The correct way to do this with sqlite4 is to use the bind API, but ** since the shell is built around the callback paradigm it would be a lot ** of work. Instead just use this hack, which is quite harmless. |
︙ | ︙ | |||
413 414 415 416 417 418 419 | ** the main program to the callback. This is used to communicate ** state and mode information. */ struct callback_data { sqlite4 *db; /* The database */ int echoOn; /* True to echo input commands */ int statsOn; /* True to display memory stats before each finalize */ | < < | 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 | ** the main program to the callback. This is used to communicate ** state and mode information. */ struct callback_data { sqlite4 *db; /* The database */ int echoOn; /* True to echo input commands */ int statsOn; /* True to display memory stats before each finalize */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite4_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ int showHeader; /* True to show column names in List or Column mode */ char *zDestTable; /* Name of destination table when MODE_Insert */ char separator[20]; /* Separator character for MODE_List */ int colWidth[100]; /* Requested width of each column when in column mode*/ int actualWidth[100]; /* Actual width of each column */ char nullvalue[20]; /* The text to print when a NULL comes back from ** the database */ struct previous_mode_data explainPrev; /* Holds the mode information just before ** .explain ON */ char outfile[FILENAME_MAX]; /* Filename for *out */ const char *zDbFilename; /* name of the database file */ const char *zVfs; /* Name of VFS to use */ FILE *pLog; /* Write log output here */ }; /* ** These are the allowed modes. */ #define MODE_Line 0 /* One column per line. Blank line between records */ |
︙ | ︙ | |||
662 663 664 665 666 667 668 | static void interrupt_handler(int NotUsed){ UNUSED_PARAMETER(NotUsed); seenInterrupt = 1; if( db ) sqlite4_interrupt(db); } #endif | | | | > | < > | < > < < | | < > | > | > | | > > > | > | < | > > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | | < | < < | < < < < < | < | < | | | | < < < < < < < < < < | | | < < < < < < < < | < < < < < < | < | | | > | > > > | > > | | | > | | > > > | < | | | | | < < | < < > < < < < < < < < < | 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 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 | static void interrupt_handler(int NotUsed){ UNUSED_PARAMETER(NotUsed); seenInterrupt = 1; if( db ) sqlite4_interrupt(db); } #endif static const char *textFromStmt( struct callback_data *p, sqlite4_stmt *pStmt, int iCol, int *pn ){ int n; const char *z; z = sqlite4_column_text(pStmt, iCol, &n); if( z==0 ){ z = p->nullvalue; n = strlen30(z); } if( pn ) *pn = n; return z; } static int shell_handle_cols( struct callback_data *p, sqlite4_stmt *pStmt ){ int nCol = sqlite4_column_count(pStmt); int i; switch( p->mode ){ case MODE_Line: break; case MODE_Explain: case MODE_Column: { for(i=0; i<nCol; i++){ const char *zCol = sqlite4_column_name(pStmt, i); int w, n; if( i<ArraySize(p->colWidth) ){ w = p->colWidth[i]; }else{ w = 0; } if( w==0 ){ w = strlen30(zCol); if( w<10 ) w = 10; textFromStmt(p, pStmt, i, &n); if( w<n ) w = n; } if( i<ArraySize(p->actualWidth) ){ p->actualWidth[i] = w; } if( p->showHeader ){ if( w<0 ){ fprintf(p->out,"%*.*s%s", -w, -w, zCol, i==nCol-1 ? "\n": " "); }else{ fprintf(p->out,"%-*.*s%s", w, w, zCol, i==nCol-1 ? "\n": " "); } } } if( p->showHeader ){ for(i=0; i<nCol; i++){ int w; if( i<ArraySize(p->actualWidth) ){ w = p->actualWidth[i]; if( w<0 ) w = -w; }else{ w = 10; } fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" "----------------------------------------------------------", i==nCol-1 ? "\n": " "); } } break; } case MODE_Semi: case MODE_List: { if( p->showHeader ){ for(i=0; i<nCol; i++){ const char *zCol = sqlite4_column_name(pStmt, i); fprintf(p->out,"%s%s", zCol, i==nCol-1 ? "\n" : p->separator); } } break; } case MODE_Html: { if( p->showHeader ){ fprintf(p->out,"<TR>"); for(i=0; i<nCol; i++){ fprintf(p->out,"<TH>"); output_html_string(p->out, sqlite4_column_name(pStmt, i)); fprintf(p->out,"</TH>\n"); } fprintf(p->out,"</TR>\n"); } break; } case MODE_Tcl: { if( p->showHeader ){ for(i=0; i<nCol; i++){ output_c_string(p->out, sqlite4_column_name(pStmt, i)); if(i<nCol-1) fprintf(p->out, "%s", p->separator); } fprintf(p->out,"\n"); } break; } case MODE_Csv: { if( p->showHeader ){ for(i=0; i<nCol; i++){ output_csv(p, sqlite4_column_name(pStmt, i), i<nCol-1); } fprintf(p->out,"\n"); } break; } case MODE_Insert: break; } return 0; } static int shell_handle_row( struct callback_data *p, sqlite4_stmt *pStmt ){ int nData = sqlite4_data_count(pStmt); int nCol = sqlite4_column_count(pStmt); int i; assert( nData>0 ); switch( p->mode ){ case MODE_Line: { int w = 5; for(i=0; i<nData; i++){ int len = strlen30(sqlite4_column_name(pStmt, i)); if( len>w ) w = len; } for(i=0; i<nData; i++){ const char *z = textFromStmt(p, pStmt, i, 0); fprintf(p->out,"%*s = %s\n", w, sqlite4_column_name(pStmt, i), z); } break; } case MODE_Explain: case MODE_Column: { for(i=0; i<nData; i++){ int w; int nActual; const char *z; if( i<ArraySize(p->actualWidth) ){ w = p->actualWidth[i]; }else{ w = 10; } z = textFromStmt(p, pStmt, i, &nActual); if( p->mode==MODE_Explain && nActual>w ){ w = nActual; } if( w<0 ){ fprintf(p->out,"%*.*s%s", -w, -w, z, i==nData-1 ? "\n": " "); }else{ fprintf(p->out,"%-*.*s%s", w, w, z, i==nData-1 ? "\n": " "); } } break; } case MODE_Semi: case MODE_List: { for(i=0; i<nData; i++){ const char *z = textFromStmt(p, pStmt, i, 0); fprintf(p->out, "%s", z); if( i<nData-1 ){ fprintf(p->out, "%s", p->separator); }else if( p->mode==MODE_Semi ){ fprintf(p->out, ";\n"); }else{ fprintf(p->out, "\n"); } } break; } case MODE_Html: { fprintf(p->out,"<TR>"); for(i=0; i<nData; i++){ fprintf(p->out,"<TD>"); output_html_string(p->out, textFromStmt(p, pStmt, i, 0)); fprintf(p->out,"</TD>\n"); } fprintf(p->out,"</TR>\n"); break; } case MODE_Tcl: { for(i=0; i<nData; i++){ output_c_string(p->out, textFromStmt(p, pStmt, i, 0)); if(i<nData-1) fprintf(p->out, "%s", p->separator); } fprintf(p->out,"\n"); break; } case MODE_Csv: { for(i=0; i<nData; i++){ output_csv(p, textFromStmt(p, pStmt, i, 0), i<nData-1); } fprintf(p->out,"\n"); break; } case MODE_Insert: { if( nData==0 ) break; fprintf(p->out, "INSERT INTO %s VALUES(", p->zDestTable); for(i=0; i<nData; i++){ int eType; /* Type of apArg[i] */ char *zSep = i>0 ? ",": ""; eType = sqlite4_column_type(pStmt, i); switch( eType ){ case SQLITE4_NULL: fprintf(p->out,"%sNULL",zSep); break; case SQLITE4_TEXT: if( zSep[0] ) fprintf(p->out,"%s",zSep); output_quoted_string(p->out, sqlite4_column_text(pStmt, i, 0)); break; case SQLITE4_INTEGER: case SQLITE4_FLOAT: fprintf(p->out, "%s%s", zSep, sqlite4_column_text(pStmt, i, 0)); break; case SQLITE4_BLOB: { int nBlob; const void *pBlob = sqlite4_column_blob(pStmt, i, &nBlob); if( zSep[0] ) fprintf(p->out, "%s", zSep); output_hex_blob(p->out, pBlob, nBlob); break; } } } fprintf(p->out,");\n"); break; } } return 0; } /* ** Set the destination table field of the callback_data structure to ** the name of the table given. Escape any quote characters in the ** table name. */ static void set_table_name(struct callback_data *p, const char *zName){ int i, n; |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | if( rc!=SQLITE4_OK ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite4_errmsg(p->db)); p->nErr++; } return rc; } | < < < < < < < < < < < < < < > | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 | if( rc!=SQLITE4_OK ){ fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite4_errmsg(p->db)); p->nErr++; } return rc; } /* ** Display memory stats. */ static int display_stats( sqlite4 *db, /* Database to query */ sqlite4_stmt *pStmt, struct callback_data *pArg, /* Pointer to struct callback_data */ int bReset /* True to reset the stats */ ){ int iCur; int iHiwtr; if( pArg && pArg->out && db ){ |
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | sqlite4_db_status(db, SQLITE4_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite4_db_status(db, SQLITE4_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); } | | | | | | < | | | < | | < < | < < | > > > | | | < < | < < | < < < < < < | < | | < < | < < < < < < | | | | | | | | | | | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < < < < | < < < < < < < | < | | < | | | | | | | | < < | < < < < < < < < < < | > > > > > | | | | | 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | sqlite4_db_status(db, SQLITE4_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; sqlite4_db_status(db, SQLITE4_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); } if( pArg && pArg->out && db && pStmt ){ iCur = sqlite4_stmt_status(pStmt, SQLITE4_STMTSTATUS_FULLSCAN_STEP, bReset); fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); iCur = sqlite4_stmt_status(pStmt, SQLITE4_STMTSTATUS_SORT, bReset); fprintf(pArg->out, "Sort Operations: %d\n", iCur); iCur = sqlite4_stmt_status(pStmt, SQLITE4_STMTSTATUS_AUTOINDEX, bReset); fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); } return 0; } /* ** Execute a statement or set of statements. Print any result rows/columns ** depending on the current mode set via the supplied callback. ** ** This is very similar to SQLite's built-in sqlite4_exec() function except ** it takes a slightly different callback and callback data argument. */ static int shell_exec( sqlite4 *db, /* An open database */ const char *zScript, /* SQL script to be evaluated */ struct callback_data *pArg /* Pointer to struct callback_data */ ){ int rc = SQLITE4_OK; /* Return Code */ const char *zSql = zScript; /* Unexecuted portion of SQL script */ while( zSql[0] && SQLITE4_OK==rc ){ int bFirst = 1; const char *zLeftover; /* Tail of unprocessed SQL */ sqlite4_stmt *pStmt = 0; /* Next statement to execute. */ rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover); if( rc!=SQLITE4_OK ) return rc; zSql = zLeftover; if( pStmt==0 ) continue; /* A comment or whitespace */ if( pArg->echoOn ){ const char *zStmtSql = sqlite4_sql(pStmt); fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); } /* Output TESTCTRL_EXPLAIN text of requested */ if( pArg->mode==MODE_Explain ){ const char *zExplain = 0; sqlite4_test_control(SQLITE4_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain); if( zExplain && zExplain[0] ){ fprintf(pArg->out, "%s", zExplain); } } rc = sqlite4_step(pStmt); shell_handle_cols(pArg, pStmt); while( rc==SQLITE4_ROW ){ shell_handle_row(pArg, pStmt); rc = sqlite4_step(pStmt); } /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pStmt, pArg, 0); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc = sqlite4_finalize(pStmt); zSql = zLeftover; } /* end while */ return rc; } /* ** This is a different callback routine used for dumping the database. ** Each row received by this callback consists of a table name, ** the table type ("index" or "table") and SQL to create the table. ** This routine should print text sufficient to recreate the table. */ static int dump_callback( void *pArg, int nVal, sqlite4_value **apVal, const char **azCol ){ int rc; const char *zTable; const char *zType; const char *zSql; const char *zPrepStmt = 0; struct callback_data *p = (struct callback_data *)pArg; UNUSED_PARAMETER(azCol); if( nVal!=3 ) return 1; zTable = sqlite4_value_text(apVal[0], 0); zType = sqlite4_value_text(apVal[1], 0); zSql = sqlite4_value_text(apVal[2], 0); if( strcmp(zTable, "sqlite_sequence")==0 ){ zPrepStmt = "DELETE FROM sqlite_sequence;\n"; }else if( strcmp(zTable, "sqlite_stat1")==0 ){ fprintf(p->out, "ANALYZE sqlite_master;\n"); }else if( strncmp(zTable, "sqlite_", 7)==0 ){ return 0; |
︙ | ︙ | |||
1583 1584 1585 1586 1587 1588 1589 | open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 1; data.mode = MODE_Column; data.colWidth[0] = 3; data.colWidth[1] = 15; data.colWidth[2] = 58; | < | | 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 | open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 1; data.mode = MODE_Column; data.colWidth[0] = 3; data.colWidth[1] = 15; data.colWidth[2] = 58; shell_exec(p->db, "PRAGMA database_list; ", &data); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite4_free(0, zErrMsg); rc = 1; } }else |
︙ | ︙ | |||
1831 1832 1833 1834 1835 1836 1837 | struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; if( nArg==1 ){ | | | < < | | < < | 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 | struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; if( nArg==1 ){ rc = shell_exec(p->db, "SELECT name FROM sqlite_master " "WHERE type='index' AND name NOT LIKE 'sqlite_%' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type='index' " "ORDER BY 1", &data); }else{ zShellStatic = azArg[1]; rc = shell_exec(p->db, "SELECT name FROM sqlite_master " "WHERE type='index' AND tbl_name LIKE shellstatic() " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type='index' AND tbl_name LIKE shellstatic() " "ORDER BY 1", &data); zShellStatic = 0; } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite4_free(0, zErrMsg); rc = 1; }else if( rc != SQLITE4_OK ){ |
︙ | ︙ | |||
2024 2025 2026 2027 2028 2029 2030 | fclose(alt); } }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ struct callback_data data; | < < | | < | < < < | | < | < < | | < | | < < | | < < < < < < < | 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 | fclose(alt); } }else if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ struct callback_data data; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; if( nArg>1 ){ int i; for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); if( strcmp(azArg[1],"sqlite_master")==0 ){ zShellStatic = "CREATE TABLE sqlite_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; rc = shell_exec(p->db, "SELECT shellstatic() AS sql", &data); zShellStatic = 0; }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ zShellStatic = "CREATE TEMP TABLE sqlite_temp_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; rc = shell_exec(p->db, "SELECT shellstatic() AS sql", &data); zShellStatic = 0; }else{ zShellStatic = azArg[1]; rc = shell_exec(p->db, "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " "WHERE lower(tbl_name) LIKE shellstatic()" " AND type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1)," " CASE type WHEN 'view' THEN x ELSE name END", &data); zShellStatic = 0; } }else{ rc = shell_exec(p->db, "SELECT sql FROM " " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" " FROM sqlite_master UNION ALL" " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" "ORDER BY substr(type,2,1)," " CASE type WHEN 'view' THEN x ELSE name END", &data); } if( rc!=SQLITE4_OK ){ fprintf(stderr,"Error: %s\n", sqlite4_errmsg(p->db)); } }else if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sqlite4_snprintf(p->separator, sizeof(p->separator), "%.*s", (int)sizeof(p->separator)-1, azArg[1]); }else |
︙ | ︙ | |||
2425 2426 2427 2428 2429 2430 2431 | ** Return the number of errors. */ static int process_input(struct callback_data *p, FILE *in){ char *zLine = 0; char *zSql = 0; int nSql = 0; int nSqlPrior = 0; | < | 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 | ** Return the number of errors. */ static int process_input(struct callback_data *p, FILE *in){ char *zLine = 0; char *zSql = 0; int nSql = 0; int nSqlPrior = 0; int rc; int errCnt = 0; int lineno = 0; int startline = 0; while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){ fflush(p->out); |
︙ | ︙ | |||
2486 2487 2488 2489 2490 2491 2492 | } zSql[nSql++] = '\n'; memcpy(&zSql[nSql], zLine, len+1); nSql += len; } if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite4_complete(zSql) ){ | < | | < < < < < | < | 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 | } zSql[nSql++] = '\n'; memcpy(&zSql[nSql], zLine, len+1); nSql += len; } if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) && sqlite4_complete(zSql) ){ open_db(p); BEGIN_TIMER; rc = shell_exec(p->db, zSql, p); END_TIMER; if( rc!=SQLITE4_OK ){ char zPrefix[100]; if( in!=0 || !stdin_is_interactive ){ sqlite4_snprintf(zPrefix, sizeof(zPrefix), "Error: near line %d:", startline); }else{ sqlite4_snprintf(zPrefix, sizeof(zPrefix), "Error:"); } fprintf(stderr, "%s %s\n", zPrefix, sqlite4_errmsg(p->db)); errCnt++; } free(zSql); zSql = 0; nSql = 0; } } |
︙ | ︙ | |||
2699 2700 2701 2702 2703 2704 2705 | argv[0], argv[argc-1]); exit(1); } return argv[i]; } int main(int argc, char **argv){ | < | 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 | argv[0], argv[argc-1]); exit(1); } return argv[i]; } int main(int argc, char **argv){ struct callback_data data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; int rc = 0; if( strcmp(sqlite4_sourceid(),SQLITE4_SOURCE_ID)!=0 ){ |
︙ | ︙ | |||
2864 2865 2866 2867 2868 2869 2870 | if( i==argc-1 ) break; z = cmdline_option_value(argc,argv,++i); if( z[0]=='.' ){ rc = do_meta_command(z, &data); if( rc && bail_on_error ) return rc; }else{ open_db(&data); | | | | < < < | | | < < < | 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 | if( i==argc-1 ) break; z = cmdline_option_value(argc,argv,++i); if( z[0]=='.' ){ rc = do_meta_command(z, &data); if( rc && bail_on_error ) return rc; }else{ open_db(&data); rc = shell_exec(data.db, z, &data); if( rc!=SQLITE4_OK ){ fprintf(stderr,"Error: %s\n", sqlite4_errmsg(data.db)); if( bail_on_error ) return rc; } } }else{ fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); fprintf(stderr,"Use -help for a list of options.\n"); return 1; } } if( zFirstCmd ){ /* Run just the command that follows the database name */ if( zFirstCmd[0]=='.' ){ rc = do_meta_command(zFirstCmd, &data); }else{ open_db(&data); rc = shell_exec(data.db, zFirstCmd, &data); if( rc!=SQLITE4_OK ){ fprintf(stderr,"Error: %s\n", sqlite4_errmsg(data.db)); return rc!=0 ? rc : 1; } } }else{ /* Run commands received from standard input */ if( stdin_is_interactive ){ char *zHome; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
427 428 429 430 431 432 433 | ** ** The second parameter passed to sqlite4_close() is currently unused. It ** is reserved for future functionality. */ int sqlite4_close(sqlite4 *, unsigned int flags); /* | > > > > > > > > > > > > > > | > | > > > > > > | > > > > > > > > > > > | | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | ** ** The second parameter passed to sqlite4_close() is currently unused. It ** is reserved for future functionality. */ int sqlite4_close(sqlite4 *, unsigned int flags); /* ** CAPIREF: Dynamically Typed Value Object ** KEYWORDS: {protected sqlite4_value} {unprotected sqlite4_value} ** ** SQLite uses the sqlite4_value object to represent all values ** that can be stored in a database table. SQLite uses dynamic typing ** for the values it stores. ^Values stored in sqlite4_value objects ** can be integers, floating point values, strings, BLOBs, or NULL. ** ** An sqlite4_value object may be either "protected" or "unprotected". ** Some interfaces require a protected sqlite4_value. Other interfaces ** will accept either a protected or an unprotected sqlite4_value. ** Every interface that accepts sqlite4_value arguments specifies ** whether or not it requires a protected sqlite4_value. ** ** The terms "protected" and "unprotected" refer to whether or not ** a mutex is held. An internal mutex is held for a protected ** sqlite4_value object but no mutex is held for an unprotected ** sqlite4_value object. If SQLite is compiled to be single-threaded ** (with [SQLITE4_THREADSAFE=0] and with [sqlite4_threadsafe()] returning 0) ** or if SQLite is run in one of reduced mutex modes ** [SQLITE4_CONFIG_SINGLETHREAD] or [SQLITE4_CONFIG_MULTITHREAD] ** then there is no distinction between protected and unprotected ** sqlite4_value objects and they can be used interchangeably. However, ** for maximum code portability it is recommended that applications ** still make the distinction between protected and unprotected ** sqlite4_value objects even when not strictly required. ** ** ^The sqlite4_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. ** ^The sqlite4_value object returned by ** [sqlite4_column_value()] is unprotected. ** Unprotected sqlite4_value objects may only be used with ** [sqlite4_result_value()] and [sqlite4_bind_value()]. ** The [sqlite4_value_blob | sqlite4_value_type()] family of ** interfaces require protected sqlite4_value objects. */ typedef struct Mem sqlite4_value; /* ** CAPIREF: One-Step Query Execution Interface ** ** The sqlite4_exec() interface is a convenience wrapper around ** [sqlite4_prepare()], [sqlite4_step()], and [sqlite4_finalize()], ** that allows an application to run multiple statements of SQL |
︙ | ︙ | |||
454 455 456 457 458 459 460 | ** sqlite4_exec() is relayed through to the 1st argument of each ** callback invocation. ^If the callback pointer to sqlite4_exec() ** is NULL, then no callback is ever invoked and result rows are ** ignored. ** ** ^If an error occurs while evaluating the SQL statements passed into ** sqlite4_exec(), then execution of the current statement stops and | | | | | | | | | | | | < < | | | | | | | | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | ** sqlite4_exec() is relayed through to the 1st argument of each ** callback invocation. ^If the callback pointer to sqlite4_exec() ** is NULL, then no callback is ever invoked and result rows are ** ignored. ** ** ^If an error occurs while evaluating the SQL statements passed into ** sqlite4_exec(), then execution of the current statement stops and ** any subsequent statements are not executed. ^If the 5th parameter ** to sqlite4_exec() is not NULL then any error message is written into ** memory obtained from [sqlite4_malloc()] and passed back through the 5th ** parameter. To avoid memory leaks, the application should invoke ** [sqlite4_free()] on error message strings returned through the 5th ** parameter of of sqlite4_exec() after the error message string is no ** longer needed. ^If the 5th parameter to sqlite4_exec() is not NULL and ** no errors occur, then sqlite4_exec() sets the pointer in its 5th ** parameter to NULL before returning. ** ** ^If an sqlite4_exec() callback returns non-zero, the sqlite4_exec() ** routine returns SQLITE4_ABORT without invoking the callback again and ** without running any subsequent SQL statements. ** ** ^The 2nd argument to the sqlite4_exec() callback function is the ** number of columns in the result. ^The 3rd argument to the sqlite4_exec() ** callback is an array of pointers to protected sqlite4_value objects ** containing the values for each column of the current row. ** ^The 4th argument to the sqlite4_exec() callback is an array of pointers ** to strings where each entry represents the name of corresponding result ** column as obtained from [sqlite4_column_name()]. ** ** ^If the 2nd parameter to sqlite4_exec() is a NULL pointer, a pointer ** to an empty string, or a pointer that contains only whitespace and/or ** SQL comments, then no SQL statements are evaluated and the database ** is not changed. ** ** Restrictions: ** ** <ul> ** <li> The application must insure that the 1st parameter to sqlite4_exec() ** is a valid and open [database connection]. ** <li> The application must not close [database connection] specified by ** the 1st parameter to sqlite4_exec() while sqlite4_exec() is running. ** <li> The application must not modify the SQL statement text passed into ** the 2nd parameter of sqlite4_exec() while sqlite4_exec() is running. ** </ul> */ int sqlite4_exec( sqlite4 *, /* An open database */ const char *zSql, /* SQL to be evaluated */ int (*)(void*,int,sqlite4_value**,const char**), /* Callback function */ void *, /* Context for callback */ char **pzErrmsg /* Error msg written here */ ); /* ** CAPIREF: Result Codes ** KEYWORDS: SQLITE4_OK {error code} {error codes} ** KEYWORDS: {result code} {result codes} ** |
︙ | ︙ | |||
1641 1642 1643 1644 1645 1646 1647 | ** CAPIREF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. ** ** The first argument, "db", is a [database connection] obtained from a | | | | | < | 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 | ** CAPIREF: Compiling An SQL Statement ** KEYWORDS: {SQL statement compiler} ** ** To execute an SQL query, it must first be compiled into a byte-code ** program using one of these routines. ** ** The first argument, "db", is a [database connection] obtained from a ** prior successful call to [sqlite4_open()]. The database connection ** must not have been closed. ** ** The second argument, "zSql", is the statement to be compiled, encoded ** as either UTF-8 or UTF-16. The sqlite4_prepare() interface uses UTF-8 ** , and sqlite4_prepare16() uses UTF-16. ** ** ^If the nByte argument is less than zero, then zSql is read up to the ** first zero terminator. ^If nByte is non-negative, then it is the maximum ** number of bytes read from zSql. ^When nByte is non-negative, the ** zSql string ends at either the first '\000' or '\u0000' character or ** the nByte-th byte, whichever comes first. If the caller knows ** that the supplied string is nul-terminated, then there is a small |
︙ | ︙ | |||
1681 1682 1683 1684 1685 1686 1687 | ** otherwise an [error code] is returned. */ int sqlite4_prepare( sqlite4 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite4_stmt **ppStmt, /* OUT: Statement handle */ | | | 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 | ** otherwise an [error code] is returned. */ int sqlite4_prepare( sqlite4 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite4_stmt **ppStmt, /* OUT: Statement handle */ const char **pzTail ); /* ** CAPIREF: Retrieving Statement SQL ** ** ^This interface can be used to retrieve a saved copy of the original ** SQL text used to create a [prepared statement] if that statement was |
︙ | ︙ | |||
1743 1744 1745 1746 1747 1748 1749 | ** to locate all prepared statements associated with a database ** connection that are in need of being reset. This can be used, ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ int sqlite4_stmt_busy(sqlite4_stmt*); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 | ** to locate all prepared statements associated with a database ** connection that are in need of being reset. This can be used, ** for example, in diagnostic routines to search for prepared ** statements that are holding a transaction open. */ int sqlite4_stmt_busy(sqlite4_stmt*); /* ** CAPIREF: SQL Function Context Object ** ** The context in which an SQL function executes is stored in an ** sqlite4_context object. ^A pointer to an sqlite4_context object ** is always first parameter to [application-defined SQL functions]. ** The application-defined SQL function implementation will pass this |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2669 2670 2671 2672 2673 2674 2675 | void sqlite4ExprAssignVarNumber(Parse*, Expr*); void sqlite4ExprDelete(sqlite4*, Expr*); ExprList *sqlite4ExprListAppend(Parse*,ExprList*,Expr*); void sqlite4ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite4ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite4ExprListDelete(sqlite4*, ExprList*); int sqlite4Init(sqlite4*, char**); | | | 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 | void sqlite4ExprAssignVarNumber(Parse*, Expr*); void sqlite4ExprDelete(sqlite4*, Expr*); ExprList *sqlite4ExprListAppend(Parse*,ExprList*,Expr*); void sqlite4ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite4ExprListSetSpan(Parse*,ExprList*,ExprSpan*); void sqlite4ExprListDelete(sqlite4*, ExprList*); int sqlite4Init(sqlite4*, char**); int sqlite4InitCallback(void*, int, sqlite4_value**, const char**); void sqlite4Pragma(Parse*,Token*,Token*,Token*,int); void sqlite4ResetInternalSchema(sqlite4*, int); void sqlite4BeginParse(Parse*,int); void sqlite4CommitInternalChanges(sqlite4*); Table *sqlite4ResultSetOfSelect(Parse*,Select*); void sqlite4OpenMasterTable(Parse *, int); void sqlite4StartTable(Parse*,Token*,Token*,int,int,int,int); |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
211 212 213 214 215 216 217 218 219 220 221 222 223 224 | void sqlite4VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite4VdbeTakeOpArray(Vdbe*, int*, int*); sqlite4_value *sqlite4VdbeGetValue(Vdbe*, int, u8); void sqlite4VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE4_OMIT_TRACE char *sqlite4VdbeExpandSql(Vdbe*, const char*); #endif void sqlite4VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite4VdbeRecordCompare(int,const void*,UnpackedRecord*); UnpackedRecord *sqlite4VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); #ifndef SQLITE4_OMIT_TRIGGER void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *); | > | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | void sqlite4VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite4VdbeTakeOpArray(Vdbe*, int*, int*); sqlite4_value *sqlite4VdbeGetValue(Vdbe*, int, u8); void sqlite4VdbeSetVarmask(Vdbe*, int); #ifndef SQLITE4_OMIT_TRACE char *sqlite4VdbeExpandSql(Vdbe*, const char*); #endif sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol); void sqlite4VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); int sqlite4VdbeRecordCompare(int,const void*,UnpackedRecord*); UnpackedRecord *sqlite4VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); #ifndef SQLITE4_OMIT_TRIGGER void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *); |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
682 683 684 685 686 687 688 689 690 691 692 693 694 695 | sqlite4_mutex_enter(pVm->db->mutex); sqlite4Error(pVm->db, SQLITE4_RANGE, 0); } pOut = (Mem*)&nullMem; } return pOut; } /* ** This function is called after invoking an sqlite4_value_XXX function on a ** column value (i.e. a value returned by evaluating an SQL expression in the ** select list of a SELECT statement) that may cause a malloc() failure. If ** malloc() has failed, the threads mallocFailed flag is cleared and the result ** code of statement pStmt set to SQLITE4_NOMEM. | > > > > > > > > > > > > > > > | 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 | sqlite4_mutex_enter(pVm->db->mutex); sqlite4Error(pVm->db, SQLITE4_RANGE, 0); } pOut = (Mem*)&nullMem; } return pOut; } /* ** Return a pointer to an sqlite4_value object that contains the value ** of column iCol of the current row of statement pStmt. ** ** Unlike columnMem(), it is the responsibility of the caller to ensure ** that the database handle mutex is held and that the value iCol is ** within the valid range. */ sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol){ Vdbe *p = (Vdbe*)pStmt; assert( sqlite4_mutex_held(p->db->mutex) ); assert( iCol<p->nResColumn && iCol>=0 ); return (sqlite4_value *)&p->pResultSet[iCol]; } /* ** This function is called after invoking an sqlite4_value_XXX function on a ** column value (i.e. a value returned by evaluating an SQL expression in the ** select list of a SELECT statement) that may cause a malloc() failure. If ** malloc() has failed, the threads mallocFailed flag is cleared and the result ** code of statement pStmt set to SQLITE4_NOMEM. |
︙ | ︙ |
Changes to test/test_main.c.
︙ | ︙ | |||
235 236 237 238 239 240 241 | sqlite4_snprintf(zPtr, 100, "%p", p); return TCL_OK; } /* ** The callback routine for sqlite4_exec_printf(). */ | | > > > > > | | | > | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | sqlite4_snprintf(zPtr, 100, "%p", p); return TCL_OK; } /* ** The callback routine for sqlite4_exec_printf(). */ static int exec_printf_cb( void *pArg, int nVal, sqlite4_value **apVal, const char **azCol ){ Tcl_DString *str = (Tcl_DString*)pArg; int i; if( Tcl_DStringLength(str)==0 ){ for(i=0; i<nVal; i++){ Tcl_DStringAppendElement(str, azCol[i] ? azCol[i] : "NULL"); } } for(i=0; i<nVal; i++){ const char *z = sqlite4_value_text(apVal[i], 0); Tcl_DStringAppendElement(str, z ? z : "NULL"); } return 0; } /* ** The I/O tracing callback. */ |
︙ | ︙ | |||
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | */ static int test_key( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ sqlite4 *db; const char *zKey; int nKey; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; zKey = argv[2]; nKey = strlen(zKey); | > < > < | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 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 | */ static int test_key( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ #ifdef SQLITE4_HAS_CODEC sqlite4 *db; const char *zKey; int nKey; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; zKey = argv[2]; nKey = strlen(zKey); sqlite4_key(db, zKey, nKey); #endif return TCL_OK; } /* ** Usage: sqlite4_rekey DB KEY ** ** Change the codec key. */ static int test_rekey( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */ ){ #ifdef SQLITE4_HAS_CODEC sqlite4 *db; const char *zKey; int nKey; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; zKey = argv[2]; nKey = strlen(zKey); sqlite4_rekey(db, zKey, nKey); #endif return TCL_OK; } /* ** Usage: sqlite4_close DB |
︙ | ︙ | |||
738 739 740 741 742 743 744 | memcpy(&p->z[p->nUsed], z, n+1); p->nUsed += n; } /* ** Invoked for each callback from sqlite4ExecFunc */ | | > > > > > | | | | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | memcpy(&p->z[p->nUsed], z, n+1); p->nUsed += n; } /* ** Invoked for each callback from sqlite4ExecFunc */ static int execFuncCallback( void *pData, int nVal, sqlite4_value **apVal, const char **azCol ){ struct dstr *p = (struct dstr*)pData; int i; for(i=0; i<nVal; i++){ if( sqlite4_value_type(apVal[i])==SQLITE4_NULL ){ dstrAppend(p, "NULL", ' '); }else{ dstrAppend(p, sqlite4_value_text(apVal[i], 0), ' '); } } return 0; } /* ** Implementation of the x_sqlite_exec() function. This function takes |
︙ | ︙ | |||
768 769 770 771 772 773 774 | */ static void sqlite4ExecFunc( sqlite4_context *context, int argc, sqlite4_value **argv ){ struct dstr x; | < | | > | | 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 | */ static void sqlite4ExecFunc( sqlite4_context *context, int argc, sqlite4_value **argv ){ struct dstr x; sqlite4 *db = (sqlite4 *)sqlite4_user_data(context); const char *zSql = sqlite4_value_text(argv[0], 0); memset(&x, 0, sizeof(x)); (void)sqlite4_exec(db, zSql, execFuncCallback, &x, 0); sqlite4_result_text(context, x.z, x.nUsed, SQLITE4_TRANSIENT, 0); sqlite4_free(0, x.z); } /* ** Implementation of tkt2213func(), a scalar function that takes exactly ** one argument. It has two interesting features: |
︙ | ︙ |