diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/copy.c | 5 | ||||
-rw-r--r-- | src/delete.c | 5 | ||||
-rw-r--r-- | src/insert.c | 4 | ||||
-rw-r--r-- | src/main.c | 7 | ||||
-rw-r--r-- | src/pragma.c | 88 | ||||
-rw-r--r-- | src/select.c | 41 | ||||
-rw-r--r-- | src/test1.c | 147 | ||||
-rw-r--r-- | src/update.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 53 | ||||
-rw-r--r-- | src/vdbe.h | 3 | ||||
-rw-r--r-- | src/vdbeInt.h | 2 | ||||
-rw-r--r-- | src/vdbeaux.c | 40 |
12 files changed, 274 insertions, 125 deletions
diff --git a/src/copy.c b/src/copy.c index 72bc5ac0c..c12de507d 100644 --- a/src/copy.c +++ b/src/copy.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the COPY command. ** -** $Id: copy.c,v 1.12 2004/05/25 23:35:18 danielk1977 Exp $ +** $Id: copy.c,v 1.13 2004/05/26 10:11:05 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -97,10 +97,9 @@ void sqlite3Copy( sqlite3VdbeAddOp(v, OP_Noop, 0, 0); sqlite3EndWriteOperation(pParse); if( db->flags & SQLITE_CountRows ){ - sqlite3VdbeAddOp(v, OP_ColumnName, 0, 1); - sqlite3VdbeChangeP3(v, -1, "rows inserted", P3_STATIC); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); } } diff --git a/src/delete.c b/src/delete.c index 0922c0684..2e69961d7 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.69 2004/05/25 23:35:18 danielk1977 Exp $ +** $Id: delete.c,v 1.70 2004/05/26 10:11:05 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -303,10 +303,9 @@ void sqlite3DeleteFrom( ** Return the number of rows that were deleted. */ if( db->flags & SQLITE_CountRows ){ - sqlite3VdbeAddOp(v, OP_ColumnName, 0, 1); - sqlite3VdbeChangeP3(v, -1, "rows deleted", P3_STATIC); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "rows deleted", P3_STATIC); } delete_from_cleanup: diff --git a/src/insert.c b/src/insert.c index 0091c6d0e..4741d968d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.106 2004/05/25 23:35:18 danielk1977 Exp $ +** $Id: insert.c,v 1.107 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -617,10 +617,10 @@ void sqlite3Insert( ** Return the number of rows inserted. */ if( db->flags & SQLITE_CountRows ){ - sqlite3VdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC); sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "rows inserted", P3_STATIC); } insert_cleanup: diff --git a/src/main.c b/src/main.c index fa9b22fee..8a4f5ce99 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.192 2004/05/26 06:58:44 danielk1977 Exp $ +** $Id: main.c,v 1.193 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -930,6 +930,11 @@ int sqlite3_prepare( if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ sqlite3VdbeSetNumCols(sParse.pVdbe, 5); + sqlite3VdbeSetColName(sParse.pVdbe, 0, "addr", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, "opcode", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, "p1", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 3, "p2", P3_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 4, "p3", P3_STATIC); } prepare_out: diff --git a/src/pragma.c b/src/pragma.c index 4d72cad37..002408bc2 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.31 2004/05/26 06:58:44 danielk1977 Exp $ +** $Id: pragma.c,v 1.32 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -129,11 +129,9 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ Vdbe *v; if( strcmp(zLeft,zRight)==0 && (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC); - sqlite3VdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC); + sqlite3VdbeSetColName(v, 0, aPragma[i].zName, P3_STATIC); sqlite3VdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0, - OP_Callback, 1, 0, - 0); + OP_Callback, 1, 0, 0); }else if( getBoolean(zRight) ){ db->flags |= aPragma[i].mask; }else{ @@ -202,12 +200,12 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 6, 0}, { OP_Integer, 0, 0, 0}, /* 5 */ - { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; int addr; if( pRight->z==pLeft->z ){ sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr+5, MAX_PAGES); }else{ @@ -242,7 +240,6 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ static VdbeOpList getCacheSize[] = { - { OP_ColumnName, 0, 1, "cache_size"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ @@ -250,6 +247,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ if( size<0 ) size = -size; sqlite3VdbeAddOp(v, OP_Integer, size, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "cache_size", P3_STATIC); sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); }else{ int size = atoi(zRight); @@ -281,24 +279,24 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft,"default_synchronous")==0 ){ static VdbeOpList getSync[] = { - { OP_ColumnName, 0, 1, "synchronous"}, { OP_ReadCookie, 0, 3, 0}, { OP_Dup, 0, 0, 0}, - { OP_If, 0, 0, 0}, /* 3 */ + { OP_If, 0, 0, 0}, /* 2 */ { OP_ReadCookie, 0, 2, 0}, { OP_Integer, 0, 0, 0}, { OP_Lt, 0, 5, 0}, { OP_AddImm, 1, 0, 0}, { OP_Callback, 1, 0, 0}, { OP_Halt, 0, 0, 0}, - { OP_AddImm, -1, 0, 0}, /* 10 */ + { OP_AddImm, -1, 0, 0}, /* 9 */ { OP_Callback, 1, 0, 0} }; int addr; if( pRight->z==pLeft->z ){ sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "synchronous", P3_STATIC); addr = sqlite3VdbeAddOpList(v, ArraySize(getSync), getSync); - sqlite3VdbeChangeP2(v, addr+3, addr+10); + sqlite3VdbeChangeP2(v, addr+2, addr+9); }else{ int size = db->cache_size; if( size<0 ) size = -size; @@ -335,11 +333,11 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ static VdbeOpList getSync[] = { - { OP_ColumnName, 0, 1, "synchronous"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "synchronous", P3_STATIC); sqlite3VdbeAddOp(v, OP_Integer, db->safety_level-1, 0); sqlite3VdbeAddOpList(v, ArraySize(getSync), getSync); }else{ @@ -371,17 +369,14 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ Table *pTab; pTab = sqlite3FindTable(db, zRight, 0); if( pTab ){ - static VdbeOpList tableInfoPreface[] = { - { OP_ColumnName, 0, 0, "cid"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 0, "type"}, - { OP_ColumnName, 3, 0, "notnull"}, - { OP_ColumnName, 4, 0, "dflt_value"}, - { OP_ColumnName, 5, 1, "pk"}, - }; int i; sqlite3VdbeSetNumCols(v, 6); - sqlite3VdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + sqlite3VdbeSetColName(v, 0, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, "type", P3_STATIC); + sqlite3VdbeSetColName(v, 3, "notnull", P3_STATIC); + sqlite3VdbeSetColName(v, 4, "dflt_value", P3_STATIC); + sqlite3VdbeSetColName(v, 5, "pk", P3_STATIC); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0; i<pTab->nCol; i++){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); @@ -402,15 +397,12 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ Table *pTab; pIdx = sqlite3FindIndex(db, zRight, 0); if( pIdx ){ - static VdbeOpList tableInfoPreface[] = { - { OP_ColumnName, 0, 0, "seqno"}, - { OP_ColumnName, 1, 0, "cid"}, - { OP_ColumnName, 2, 1, "name"}, - }; int i; pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface); + sqlite3VdbeSetColName(v, 0, "seqno", P3_STATIC); + sqlite3VdbeSetColName(v, 1, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 2, "name", P3_STATIC); for(i=0; i<pIdx->nColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp(v, OP_Integer, i, 0); @@ -432,14 +424,10 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } if( pTab && pIdx ){ int i = 0; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "seq"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 1, "unique"}, - }; - sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); + sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, "unique", P3_STATIC); while(pIdx){ sqlite3VdbeAddOp(v, OP_Integer, i, 0); sqlite3VdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0); @@ -461,16 +449,12 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ } if( pTab && pFK ){ int i = 0; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "id"}, - { OP_ColumnName, 1, 0, "seq"}, - { OP_ColumnName, 2, 0, "table"}, - { OP_ColumnName, 3, 0, "from"}, - { OP_ColumnName, 4, 1, "to"}, - }; - - sqlite3VdbeSetNumCols(v, 6); - sqlite3VdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); + sqlite3VdbeSetNumCols(v, 5); + sqlite3VdbeSetColName(v, 0, "id", P3_STATIC); + sqlite3VdbeSetColName(v, 1, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 2, "table", P3_STATIC); + sqlite3VdbeSetColName(v, 3, "from", P3_STATIC); + sqlite3VdbeSetColName(v, 4, "to", P3_STATIC); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ @@ -490,14 +474,10 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ if( sqlite3StrICmp(zLeft, "database_list")==0 ){ int i; - static VdbeOpList indexListPreface[] = { - { OP_ColumnName, 0, 0, "seq"}, - { OP_ColumnName, 1, 0, "name"}, - { OP_ColumnName, 2, 1, "file"}, - }; - sqlite3VdbeSetNumCols(v, 3); - sqlite3VdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface); + sqlite3VdbeSetColName(v, 0, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, "file", P3_STATIC); for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); @@ -523,12 +503,12 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ static VdbeOpList getTmpDbLoc[] = { - { OP_ColumnName, 0, 1, "temp_store"}, { OP_Callback, 1, 0, 0}, }; if( pRight->z==pLeft->z ){ sqlite3VdbeAddOp(v, OP_Integer, db->temp_store, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "temp_store", P3_STATIC); sqlite3VdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); }else{ changeTempStorage(pParse, zRight); @@ -548,11 +528,11 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ */ if( sqlite3StrICmp(zLeft, "default_temp_store")==0 ){ static VdbeOpList getTmpDbLoc[] = { - { OP_ColumnName, 0, 1, "temp_store"}, { OP_ReadCookie, 0, 5, 0}, { OP_Callback, 1, 0, 0}}; if( pRight->z==pLeft->z ){ sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "temp_store", P3_STATIC); sqlite3VdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc); }else{ sqlite3BeginWriteOperation(pParse, 0, 0); @@ -582,7 +562,6 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ static VdbeOpList initCode[] = { { OP_Integer, 0, 0, 0}, { OP_MemStore, 0, 1, 0}, - { OP_ColumnName, 0, 1, "integrity_check"}, }; /* Code that appears at the end of the integrity check. If no error @@ -599,6 +578,7 @@ void sqlite3Pragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ /* Initialize the VDBE program */ sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); sqlite3VdbeAddOpList(v, ArraySize(initCode), initCode); /* Do an integrity check on each database file */ diff --git a/src/select.c b/src/select.c index 52c35ebce..2340cb5b4 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.176 2004/05/26 06:18:38 danielk1977 Exp $ +** $Id: select.c,v 1.177 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -682,6 +682,11 @@ static void generateColumnNames( sqlite *db = pParse->db; int fullNames, shortNames; + /* If this is an EXPLAIN, skip this step */ + if( pParse->explain ){ + return SQLITE_OK; + } + assert( v!=0 ); if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return; pParse->colNamesSet = 1; @@ -695,7 +700,7 @@ static void generateColumnNames( if( p==0 ) continue; if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; - sqlite3VdbeOp3(v, OP_ColumnName, i, p2, zName, 0); + sqlite3VdbeSetColName(v, i, zName, 0); continue; } if( p->op==TK_COLUMN && pTabList ){ @@ -713,8 +718,8 @@ static void generateColumnNames( zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ - int addr = sqlite3VdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n); - sqlite3VdbeCompressSpace(v, addr); + sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + /* sqlite3VdbeCompressSpace(v, addr); */ }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; @@ -722,18 +727,18 @@ static void generateColumnNames( zTab = pTabList->a[j].zAlias; if( fullNames || zTab==0 ) zTab = pTab->zName; sqlite3SetString(&zName, zTab, ".", zCol, 0); - sqlite3VdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC); + sqlite3VdbeSetColName(v, i, zName, P3_DYNAMIC); }else{ - sqlite3VdbeOp3(v, OP_ColumnName, i, p2, zCol, 0); + sqlite3VdbeSetColName(v, i, zCol, 0); } }else if( p->span.z && p->span.z[0] ){ - int addr = sqlite3VdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n); - sqlite3VdbeCompressSpace(v, addr); + sqlite3VdbeSetColName(v, i, p->span.z, p->span.n); + /* sqlite3VdbeCompressSpace(v, addr); */ }else{ char zName[30]; assert( p->op!=TK_COLUMN || pTabList==0 ); sprintf(zName, "column%d", i+1); - sqlite3VdbeOp3(v, OP_ColumnName, i, p2, zName, 0); + sqlite3VdbeSetColName(v, i, zName, 0); } } } @@ -1429,7 +1434,6 @@ static int multiSelect( assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); - generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); @@ -1500,7 +1504,6 @@ static int multiSelect( assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); - generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); @@ -1942,9 +1945,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ */ v = sqlite3GetVdbe(pParse); if( v==0 ) return 0; - if( eDest==SRT_Callback ){ - generateColumnTypes(pParse, p->pSrc, p->pEList); - } /* If the output is destined for a temporary table, open that table. */ @@ -2294,19 +2294,6 @@ int sqlite3Select( */ computeLimitRegisters(pParse, p); - /* Identify column types if we will be using a callback. This - ** step is skipped if the output is going to a destination other - ** than a callback. - ** - ** We have to do this separately from the creation of column names - ** above because if the pTabList contains views then they will not - ** have been resolved and we will not know the column types until - ** now. - */ - if( eDest==SRT_Callback ){ - generateColumnTypes(pParse, pTabList, pEList); - } - /* If the output is destined for a temporary table, open that table. */ if( eDest==SRT_TempTable ){ diff --git a/src/test1.c b/src/test1.c index cc9aa3b5b..0d3823c09 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.56 2004/05/26 06:58:44 danielk1977 Exp $ +** $Id: test1.c,v 1.57 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -742,6 +742,7 @@ static int test_finalize( if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; rc = sqlite3_finalize(pStmt); + Tcl_SetResult(interp, errorName(rc), TCL_STATIC); if( rc ){ return TCL_ERROR; } @@ -1406,6 +1407,66 @@ static int test_column_data16( } /* +** Usage: sqlite3_column_name STMT column +** +** Advance the statement to the next row. +*/ +static int test_column_name( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + Tcl_SetResult(interp, (char *)sqlite3_column_name(pStmt, col), 0); + + return TCL_OK; +} + +/* +** Usage: sqlite3_column_name16 STMT column +** +** Advance the statement to the next row. +*/ +static int test_column_name16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + Tcl_Obj *pRet; + const void *zName16; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + zName16 = sqlite3_column_name16(pStmt, col); + pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2); + Tcl_SetObjResult(interp, pRet); + + return TCL_OK; +} + +/* ** Usage: sqlite3_column_count STMT ** ** Return the number of columns returned by the sql statement STMT. @@ -1431,6 +1492,82 @@ static int test_column_count( } /* +** Usage: sqlite3_column_type STMT column +** +** Return the type of the data in column 'column' of the current row. +*/ +static int test_column_type( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + int tp; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + tp = sqlite3_column_type(pStmt, col); + switch( tp ){ + case SQLITE3_INTEGER: + Tcl_SetResult(interp, "INTEGER", TCL_STATIC); + break; + case SQLITE3_NULL: + Tcl_SetResult(interp, "NULL", TCL_STATIC); + break; + case SQLITE3_FLOAT: + Tcl_SetResult(interp, "FLOAT", TCL_STATIC); + break; + case SQLITE3_TEXT: + Tcl_SetResult(interp, "TEXT", TCL_STATIC); + break; + case SQLITE3_BLOB: + Tcl_SetResult(interp, "BLOB", TCL_STATIC); + break; + default: + assert(0); + } + + return TCL_OK; +} + +/* +** Usage: sqlite3_column_int STMT column +** +** Return the data in column 'column' of the current row cast as an +** integer. +*/ +static int test_column_int( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int col; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " STMT column", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; + + Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_int(pStmt, col))); + return TCL_OK; +} + +/* ** Usage: sqlite3_data_count STMT ** ** Return the number of columns returned by the sql statement STMT. @@ -1551,8 +1688,12 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_reset", (Tcl_ObjCmdProc*)test_reset }, { "sqlite3_step", (Tcl_ObjCmdProc*)test_step}, { "sqlite3_column_data", (Tcl_ObjCmdProc*)test_column_data }, - { "sqlite3_column_data16", (Tcl_ObjCmdProc*)test_column_data16 }, - { "sqlite3_column_count", (Tcl_ObjCmdProc*)test_column_count }, + { "sqlite3_column_data16", (Tcl_ObjCmdProc*)test_column_data16 }, + { "sqlite3_column_count", (Tcl_ObjCmdProc*)test_column_count }, + { "sqlite3_column_name", (Tcl_ObjCmdProc*)test_column_name }, + { "sqlite3_column_name16", (Tcl_ObjCmdProc*)test_column_name16 }, + { "sqlite3_column_type", (Tcl_ObjCmdProc*)test_column_type }, + { "sqlite3_column_int", (Tcl_ObjCmdProc*)test_column_int }, { "sqlite3_data_count", (Tcl_ObjCmdProc*)test_data_count }, { "add_reverse_collating_func", (Tcl_ObjCmdProc*)reverse_collfunc }, }; diff --git a/src/update.c b/src/update.c index 8f3c8edb3..88c683f56 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.79 2004/05/25 23:35:19 danielk1977 Exp $ +** $Id: update.c,v 1.80 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -446,9 +446,9 @@ void sqlite3Update( ** Return the number of rows that were changed. */ if( db->flags & SQLITE_CountRows && !pParse->trigStack ){ - sqlite3VdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC); sqlite3VdbeAddOp(v, OP_Callback, 1, 0); sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, "rows updated", P3_STATIC); } update_cleanup: diff --git a/src/vdbe.c b/src/vdbe.c index f971a0308..3b1d5d060 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.332 2004/05/26 06:18:38 danielk1977 Exp $ +** $Id: vdbe.c,v 1.333 2004/05/26 10:11:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -762,16 +762,36 @@ double sqlite3_column_float(sqlite3_stmt *pStmt, int i){ */ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ Vdbe *p = (Vdbe *)pStmt; + Mem *pColName; if( N>=sqlite3_column_count(pStmt) || N<0 ){ sqlite3Error(p->db, SQLITE_RANGE, 0); return 0; } - return p->azColName[N]; + pColName = &(p->aColName[N]); + return sqlite3_value_data(pColName); } /* +** Return the name of the 'i'th column of the result set of SQL statement +** pStmt, encoded as UTF-16. +*/ +const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pColName; + + if( N>=sqlite3_column_count(pStmt) || N<0 ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return 0; + } + + pColName = &(p->aColName[N]); + return sqlite3_value_data16(pColName); +} + + +/* ** Return the type of the value stored in the sqlite_value* object. */ int sqlite3_value_type(sqlite3_value* pVal){ @@ -801,7 +821,6 @@ int sqlite3_value_type(sqlite3_value* pVal){ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int vals; Vdbe *p = (Vdbe *)pStmt; - int f; vals = sqlite3_data_count(pStmt); if( i>=vals || i<0 ){ @@ -809,24 +828,7 @@ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ return 0; } - f = p->pTos[(1-vals)+i].flags; - - if( f&MEM_Null ){ - return SQLITE3_NULL; - } - if( f&MEM_Int ){ - return SQLITE3_INTEGER; - } - if( f&MEM_Real ){ - return SQLITE3_FLOAT; - } - if( f&MEM_Str ){ - return SQLITE3_TEXT; - } - if( f&MEM_Blob ){ - return SQLITE3_BLOB; - } - assert(0); + return sqlite3_value_type(&(p->pTos[(1-vals)+i])); } /* @@ -869,14 +871,6 @@ static const void *columnName16(sqlite3_stmt *pStmt, int i, int decltype){ } /* -** Return the name of the 'i'th column of the result set of SQL statement -** pStmt, encoded as UTF-16. -*/ -const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int i){ - return columnName16(pStmt, i, 0); -} - -/* ** Return the column declaration type (if applicable) of the 'i'th column ** of the result set of SQL statement pStmt, encoded as UTF-8. */ @@ -2010,6 +2004,7 @@ case OP_Push: { ** value of the OP_ColumnName that has P2==1. */ case OP_ColumnName: { + assert(0); assert( pOp->p1>=0 && pOp->p1<p->nOp ); p->azColName[pOp->p1] = pOp->p3; p->nCallback = 0; diff --git a/src/vdbe.h b/src/vdbe.h index 130aaff0a..80ecb0a78 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.82 2004/05/25 23:35:20 danielk1977 Exp $ +** $Id: vdbe.h,v 1.83 2004/05/26 10:11:07 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -121,6 +121,7 @@ void sqlite3VdbeCompressSpace(Vdbe*,int); int sqlite3VdbeReset(Vdbe*,char **); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); +int sqlite3VdbeSetColName(Vdbe*, int, const char *, int); #ifndef NDEBUG void sqlite3VdbeComment(Vdbe*, const char*, ...); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 77f5f7c18..e1f5b4e9b 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -327,6 +327,7 @@ struct Vdbe { Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ + Mem *aColName; /* Column names to return */ char **azColName; /* Becomes the 4th parameter to callbacks */ void **azColName16; /* UTF-16 encoded equivalent of azColName */ int nCursor; /* Number of slots in apCsr[] */ @@ -401,3 +402,4 @@ int sqlite3VdbeList(Vdbe*); int sqlite3VdbeSetEncoding(Mem *, u8); int sqlite3VdbeMemCopy(Mem*, const Mem*); int sqlite3VdbeMemNulTerminate(Mem *); +int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, int); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 4167eb78c..60158fd32 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -873,10 +873,50 @@ static void Cleanup(Vdbe *p){ ** be called on an SQL statement before sqlite3_step(). */ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ + assert( 0==p->nResColumn ); p->nResColumn = nResColumn; } /* +** Set the name of the idx'th column to be returned by the SQL statement. +** zName must be a pointer to a nul terminated string. +** +** This call must be made after a call to sqlite3VdbeSetNumCols(). +** +** Parameter N may be either P3_DYNAMIC or P3_STATIC. +*/ +int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ + int rc; + Mem *pColName; + assert( idx<p->nResColumn ); + + /* If the Vdbe.aColName array has not yet been allocated, allocate + ** it now. + */ + if( !p->aColName ){ + int i; + p->aColName = (Mem *)sqliteMalloc(sizeof(Mem)*p->nResColumn); + if( !p->aColName ){ + return SQLITE_NOMEM; + } + for(i=0; i<p->nResColumn; i++){ + p->aColName[i].flags = MEM_Null; + } + } + + pColName = &(p->aColName[idx]); + if( N==0 ){ + rc = MemSetStr(pColName, zName, -1, TEXT_Utf8, 1); + }else{ + rc = MemSetStr(pColName, zName, N, TEXT_Utf8, N>0); + } + if( rc==SQLITE_OK && N==P3_DYNAMIC ){ + pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn; + } + return rc; +} + +/* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** |