Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | All the code is now in place for SQLite to distinguish between NUMERIC and TEXT datatypes. Still need to turn on the new code and test it. (CVS 659) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b4737a16c997a6c139d616211fb6bc4b |
User & Date: | drh 2002-07-05 21:42:36.000 |
Context
2002-07-06
| ||
16:28 | Fix for bug #94: Be sure to journal pages that are added to the freelist then removed from the freelist and reused during the same transaction. (CVS 660) (check-in: db178646a0 user: drh tags: trunk) | |
2002-07-05
| ||
21:42 | All the code is now in place for SQLite to distinguish between NUMERIC and TEXT datatypes. Still need to turn on the new code and test it. (CVS 659) (check-in: b4737a16c9 user: drh tags: trunk) | |
2002-07-02
| ||
13:05 | Fix for ticket #92: Correct the sqliteExprCompare() function so that is takes into account the iTable and iColumn fields of the Expr structure. Otherwise, "min(a)" and "min(b)" will compare equal to each other in views. (CVS 658) (check-in: 85793a4f03 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.101 2002/07/05 21:42:36 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
459 460 461 462 463 464 465 466 467 468 469 470 471 472 | if( isspace(c) ) continue; z[j++] = c; } z[j] = 0; pCol->sortOrder = SQLITE_SO_NUM; for(i=0; z[i]; i++){ switch( z[i] ){ case 'c': case 'C': { if( sqliteStrNICmp(&z[i],"char",4)==0 || sqliteStrNICmp(&z[i],"clob",4)==0 ){ pCol->sortOrder = SQLITE_SO_TEXT; return; } | > > > > > > > > | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 | if( isspace(c) ) continue; z[j++] = c; } z[j] = 0; pCol->sortOrder = SQLITE_SO_NUM; for(i=0; z[i]; i++){ switch( z[i] ){ case 'b': case 'B': { if( sqliteStrNICmp(&z[i],"blob",4)==0 ){ pCol->sortOrder = SQLITE_SO_TEXT; return; } break; } case 'c': case 'C': { if( sqliteStrNICmp(&z[i],"char",4)==0 || sqliteStrNICmp(&z[i],"clob",4)==0 ){ pCol->sortOrder = SQLITE_SO_TEXT; return; } |
︙ | ︙ | |||
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 | */ if( !pParse->explain ){ sqliteUnlinkAndDeleteTable(db, pTable); db->flags |= SQLITE_InternChanges; } sqliteViewResetAll(db); } /* ** Create a new index for an SQL table. pIndex is the name of the index ** and pTable is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable ** as the table to be indexed. pParse->pNewTable is a table that is | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | */ if( !pParse->explain ){ sqliteUnlinkAndDeleteTable(db, pTable); db->flags |= SQLITE_InternChanges; } sqliteViewResetAll(db); } /* ** This routine constructs a P3 string suitable for an OP_MakeIdxKey ** opcode and adds that P3 string to the most recently inserted instruction ** in the virtual machine. The P3 string consists of a single character ** for each column in the index pIdx of table pTab. If the column uses ** a numeric sort order, then the P3 string character corresponding to ** that column is 'n'. If the column uses a text sort order, then the ** P3 string is 't'. See the OP_MakeIdxKey opcode documentation for ** additional information. See also the sqliteAddKeyType() routine. */ void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ char *zType; Table *pTab; int i, n; assert( pIdx!=0 && pIdx->pTable!=0 ); pTab = pIdx->pTable; n = pIdx->nColumn; zType = sqliteMalloc( n+1 ); if( zType==0 ) return; for(i=0; i<n; i++){ int iCol = pIdx->aiColumn[i]; assert( iCol>=0 && iCol<pTab->nCol ); if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ zType[i] = 't'; }else{ zType[i] = 'n'; } } zType[n] = 0; sqliteVdbeChangeP3(v, -1, zType, n); sqliteFree(zType); } /* ** Create a new index for an SQL table. pIndex is the name of the index ** and pTable is the name of the table that is to be indexed. Both will ** be NULL for a primary key or an index that is created to satisfy a ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable ** as the table to be indexed. pParse->pNewTable is a table that is |
︙ | ︙ | |||
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 | lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); for(i=0; i<pIndex->nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->onError!=OE_None); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); sqliteVdbeAddOp(v, OP_Close, 2, 0); sqliteVdbeAddOp(v, OP_Close, 1, 0); } if( pTable!=0 ){ | > | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 | lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); for(i=0; i<pIndex->nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIndex); sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->onError!=OE_None); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); sqliteVdbeAddOp(v, OP_Close, 2, 0); sqliteVdbeAddOp(v, OP_Close, 1, 0); } if( pTable!=0 ){ |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** ** $Id: delete.c,v 1.39 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" /* ** Given a table name, find the corresponding table and make sure the ** table is writeable. Generate an error and return NULL if not. If |
︙ | ︙ | |||
257 258 259 260 261 262 263 | /* This is the beginning of the delete loop when there are no ** row triggers */ if( !row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); } /* Delete the row */ | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | /* This is the beginning of the delete loop when there are no ** row triggers */ if( !row_triggers_exist ){ addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end); } /* Delete the row */ sqliteGenerateRowDelete(db, v, pTab, base, pParse->trigStack==0); /* If there are row triggers, close all cursors then invoke ** the AFTER triggers */ if( row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum); |
︙ | ︙ | |||
325 326 327 328 329 330 331 332 333 334 335 336 337 338 | ** of the stack. ** ** This routine pops the top of the stack to remove the record number ** and then generates code to remove both the table record and all index ** entries that point to that record. */ void sqliteGenerateRowDelete( Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, base, 0); | > | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 | ** of the stack. ** ** This routine pops the top of the stack to remove the record number ** and then generates code to remove both the table record and all index ** entries that point to that record. */ void sqliteGenerateRowDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ int count /* Increment the row change counter */ ){ int addr; addr = sqliteVdbeAddOp(v, OP_NotExists, base, 0); sqliteGenerateRowIndexDelete(db, v, pTab, base, 0); sqliteVdbeAddOp(v, OP_Delete, base, count); sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* ** This routine generates VDBE code that causes the deletion of all ** index entries associated with a single row of a single table. |
︙ | ︙ | |||
354 355 356 357 358 359 360 361 362 363 364 365 366 367 | ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number base+i for the i-th index. ** ** 3. The "base" cursor must be pointing to the row that is to be ** deleted. */ void sqliteGenerateRowIndexDelete( Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ ){ int i; Index *pIdx; | > | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 | ** 2. Read/write cursors for all indices of pTab must be open as ** cursor number base+i for the i-th index. ** ** 3. The "base" cursor must be pointing to the row that is to be ** deleted. */ void sqliteGenerateRowIndexDelete( sqlite *db, /* The database containing the index */ Vdbe *v, /* Generate code into this VDBE */ Table *pTab, /* Table containing the row to be deleted */ int base, /* Cursor number for the table */ char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */ ){ int i; Index *pIdx; |
︙ | ︙ | |||
375 376 377 378 379 380 381 382 383 384 | if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, j, 0); }else{ sqliteVdbeAddOp(v, OP_Column, base, idx); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0); } } | > | 377 378 379 380 381 382 383 384 385 386 387 | if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, j, 0); }else{ sqliteVdbeAddOp(v, OP_Column, base, idx); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); if( db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx); sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0); } } |
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.63 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
612 613 614 615 616 617 618 619 620 621 622 623 624 625 | if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); }else{ sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); } } jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); onError = pIdx->onError; if( onError==OE_None ) continue; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = pParse->db->onError; if( onError==OE_Default ) onError = OE_Abort; | > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | if( idx==pTab->iPKey ){ sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); }else{ sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); } } jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0); if( pParse->db->file_format>=3 ) sqliteAddIdxKeyType(v, pIdx); onError = pIdx->onError; if( onError==OE_None ) continue; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = pParse->db->onError; if( onError==OE_Default ) onError = OE_Abort; |
︙ | ︙ | |||
636 637 638 639 640 641 642 | case OE_Ignore: { assert( seenReplace==0 ); sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0); sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { | | | 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | case OE_Ignore: { assert( seenReplace==0 ); sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0); sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest); break; } case OE_Replace: { sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0); if( isUpdate ){ sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } seenReplace = 1; break; } |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.77 2002/07/05 21:42:37 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
390 391 392 393 394 395 396 | orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). { A = sqliteExprListAppend(X,Y,0); if( A ) A->a[A->nExpr-1].sortOrder = C+Z; } | | | | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). { A = sqliteExprListAppend(X,Y,0); if( A ) A->a[A->nExpr-1].sortOrder = C+Z; } sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). { A = sqliteExprListAppend(0,Y,0); if( A ) A->a[0].sortOrder = C+Z; } sortitem(A) ::= expr(X). {A = X;} %type sortorder {int} %type collate {int} sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.103 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
311 312 313 314 315 316 317 | */ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ char *zSortOrder; int i; zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 ); if( zSortOrder==0 ) return; for(i=0; i<pOrderBy->nExpr; i++){ | > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > | < < > > > > > > > | < < < < < > | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 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 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | */ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){ char *zSortOrder; int i; zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 ); if( zSortOrder==0 ) return; for(i=0; i<pOrderBy->nExpr; i++){ int order = pOrderBy->a[i].sortOrder; int type; int c; if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ type = SQLITE_SO_TEXT; }else if( (order & SQLITE_SO_TYPEMASK)==SQLITE_SO_NUM ){ type = SQLITE_SO_NUM; }else if( pParse->db->file_format>=3 ){ type = sqliteExprType(pOrderBy->a[i].pExpr); }else{ type = SQLITE_SO_NUM; } if( (order & SQLITE_SO_DIRMASK)==SQLITE_SO_ASC ){ c = type==SQLITE_SO_TEXT ? 'A' : '+'; }else{ c = type==SQLITE_SO_TEXT ? 'D' : '-'; } zSortOrder[i] = c; sqliteExprCode(pParse, pOrderBy->a[i].pExpr); } zSortOrder[pOrderBy->nExpr] = 0; sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0); sqliteVdbeChangeP3(v, -1, zSortOrder, strlen(zSortOrder)); sqliteFree(zSortOrder); sqliteVdbeAddOp(v, OP_SortPut, 0, 0); } /* ** This routine adds a P3 argument to the last VDBE opcode that was ** inserted. The P3 argument added is a string suitable for the ** OP_MakeKey or OP_MakeIdxKey opcodes. The string consists of ** characters 't' or 'n' depending on whether or not the various ** fields of the key to be generated should be treated as numeric ** or as text. See the OP_MakeKey and OP_MakeIdxKey opcode ** documentation for additional information about the P3 string. ** See also the sqliteAddIdxKeyType() routine. */ void sqliteAddKeyType(Vdbe *v, ExprList *pEList){ int nColumn = pEList->nExpr; char *zType = sqliteMalloc( nColumn+1 ); int i; if( zType==0 ) return; for(i=0; i<nColumn; i++){ zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't'; } zType[i] = 0; sqliteVdbeChangeP3(v, -1, zType, nColumn); sqliteFree(zType); } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 ** then data is pulled from srcTab and pEList is used only to get the ** datatypes for each column. */ static int selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ int distinct, /* If >=0, make sure results are distinct */ int eDest, /* How to dispose of the results */ int iParm, /* An argument to the disposal method */ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ ){ Vdbe *v = pParse->pVdbe; int i; if( v==0 ) return 0; assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ if( pOrderBy==0 ){ if( p->nOffset>0 ){ int addr = sqliteVdbeCurrentAddr(v); sqliteVdbeAddOp(v, OP_MemIncr, p->nOffset, addr+2); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); } if( p->nLimit>=0 ){ sqliteVdbeAddOp(v, OP_MemIncr, p->nLimit, iBreak); } } /* Pull the requested columns. */ if( nColumn>0 ){ for(i=0; i<nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, srcTab, i); } }else{ nColumn = pEList->nExpr; for(i=0; i<pEList->nExpr; i++){ sqliteExprCode(pParse, pEList->a[i].pExpr); } } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( distinct>=0 && pEList && pEList->nExpr>0 ){ #if NULL_ALWAYS_DISTINCT sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7); #endif sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pEList); sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0); } |
︙ | ︙ | |||
1115 1116 1117 1118 1119 1120 1121 | if( eDest==SRT_Callback ){ generateColumnNames(pParse, p->base, 0, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); iStart = sqliteVdbeCurrentAddr(v); | | | 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 | if( eDest==SRT_Callback ){ generateColumnNames(pParse, p->base, 0, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); iStart = sqliteVdbeCurrentAddr(v); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; sqliteVdbeResolveLabel(v, iCont); sqliteVdbeAddOp(v, OP_Next, unionTab, iStart); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, unionTab, 0); |
︙ | ︙ | |||
1171 1172 1173 1174 1175 1176 1177 | generateColumnNames(pParse, p->base, 0, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); | | | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 | generateColumnNames(pParse, p->base, 0, p->pEList); } iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; sqliteVdbeResolveLabel(v, iCont); sqliteVdbeAddOp(v, OP_Next, tab1, iStart); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, tab2, 0); |
︙ | ︙ | |||
1543 1544 1545 1546 1547 1548 1549 | sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; cont = sqliteVdbeMakeLabel(v); | | | 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 | sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; cont = sqliteVdbeMakeLabel(v); selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont); sqliteVdbeResolveLabel(v, cont); sqliteVdbeAddOp(v, OP_Close, base, 0); return 1; } /* ** Generate code for the given SELECT statement. |
︙ | ︙ | |||
1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 | else{ if( pGroupBy ){ int lbl1; for(i=0; i<pGroupBy->nExpr; i++){ sqliteExprCode(pParse, pGroupBy->a[i].pExpr); } sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0); lbl1 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1); for(i=0; i<pParse->nAgg; i++){ if( pParse->aAgg[i].isAgg ) continue; sqliteExprCode(pParse, pParse->aAgg[i].pExpr); sqliteVdbeAddOp(v, OP_AggSet, 0, i); } | > | 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 | else{ if( pGroupBy ){ int lbl1; for(i=0; i<pGroupBy->nExpr; i++){ sqliteExprCode(pParse, pGroupBy->a[i].pExpr); } sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0); if( pParse->db->file_format>=3 ) sqliteAddKeyType(v, pGroupBy); lbl1 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1); for(i=0; i<pParse->nAgg; i++){ if( pParse->aAgg[i].isAgg ) continue; sqliteExprCode(pParse, pParse->aAgg[i].pExpr); sqliteVdbeAddOp(v, OP_AggSet, 0, i); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.134 2002/07/05 21:42:37 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
867 868 869 870 871 872 873 874 875 876 877 878 879 880 | int sqliteIdListIndex(IdList*,const char*); SrcList *sqliteSrcListAppend(SrcList*, Token*); void sqliteSrcListAddAlias(SrcList*, Token*); void sqliteIdListDelete(IdList*); void sqliteSrcListDelete(SrcList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*); Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqliteSelectDelete(Select*); void sqliteSelectUnbind(Select*); Table *sqliteTableNameToTable(Parse*, const char*); SrcList *sqliteTableTokenToSrcList(Parse*, Token*); | > > | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | int sqliteIdListIndex(IdList*,const char*); SrcList *sqliteSrcListAppend(SrcList*, Token*); void sqliteSrcListAddAlias(SrcList*, Token*); void sqliteIdListDelete(IdList*); void sqliteSrcListDelete(SrcList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); void sqliteAddKeyType(Vdbe*, ExprList*); void sqliteAddIdxKeyType(Vdbe*, Index*); int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*); Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqliteSelectDelete(Select*); void sqliteSelectUnbind(Select*); Table *sqliteTableNameToTable(Parse*, const char*); SrcList *sqliteTableTokenToSrcList(Parse*, Token*); |
︙ | ︙ | |||
905 906 907 908 909 910 911 | void sqliteBeginTransaction(Parse*, int); void sqliteCommitTransaction(Parse*); void sqliteRollbackTransaction(Parse*); char *sqlite_mprintf(const char *, ...); int sqliteExprIsConstant(Expr*); int sqliteExprIsInteger(Expr*, int*); int sqliteIsRowid(const char*); | | | | 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 | void sqliteBeginTransaction(Parse*, int); void sqliteCommitTransaction(Parse*); void sqliteRollbackTransaction(Parse*); char *sqlite_mprintf(const char *, ...); int sqliteExprIsConstant(Expr*); int sqliteExprIsInteger(Expr*, int*); int sqliteIsRowid(const char*); void sqliteGenerateRowDelete(sqlite*, Vdbe*, Table*, int, int); void sqliteGenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*); void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int); void sqliteBeginWriteOperation(Parse*, int); void sqliteEndWriteOperation(Parse*); void sqliteExprMoveStrings(Expr*, int); void sqliteExprListMoveStrings(ExprList*, int); void sqliteSelectMoveStrings(Select*, int); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** ** $Id: update.c,v 1.47 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. */ void sqliteUpdate( |
︙ | ︙ | |||
315 316 317 318 319 320 321 | /* Do constraint checks */ sqliteGenerateConstraintChecks(pParse, pTab, base, aIdxUsed, chngRecno, 1, onError, addr); /* Delete the old indices for the current record. */ | | | 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | /* Do constraint checks */ sqliteGenerateConstraintChecks(pParse, pTab, base, aIdxUsed, chngRecno, 1, onError, addr); /* Delete the old indices for the current record. */ sqliteGenerateRowIndexDelete(db, v, pTab, base, aIdxUsed); /* If changing the record number, delete the old record. */ if( chngRecno ){ sqliteVdbeAddOp(v, OP_Delete, base, 0); } |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.47 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
701 702 703 704 705 706 707 | ** ** +one\000-two\000+three\000\000 ** ** Both arguments will have the same number of strings. This routine ** returns negative, zero, or positive if the first argument is less ** than, equal to, or greater than the first. (Result is a-b). ** | | | > > > > | | > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | 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 | ** ** +one\000-two\000+three\000\000 ** ** Both arguments will have the same number of strings. This routine ** returns negative, zero, or positive if the first argument is less ** than, equal to, or greater than the first. (Result is a-b). ** ** Each string begins with one of the characters "+", "-", "A", "D". ** This character determines the sort order and collating sequence: ** ** + Sort numerically in ascending order ** - Sort numerically in descending order ** A Sort as strings in ascending order ** D Sort as strings in descending order. ** ** For the "+" and "-" sorting, pure numeric strings (strings for which the ** isNum() function above returns TRUE) always compare less than strings ** that are not pure numerics. Within non-numeric strings, substrings ** of digits compare in numerical order. Finally, case is used only ** to break a tie. ** ** Note that the sort order imposed by the rules above is different ** from the ordering defined by the "<", "<=", ">", and ">=" operators ** of expressions. The operators compare non-numeric strings in ** lexigraphical order. This routine does the additional processing ** to sort substrings of digits into numerical order and to use case ** only as a tie-breaker. ** ** The special rules above apply only to numeric sorting, when the ** prefix is "+" or "-". If the prefix is "A" or "D" then plain old ** "strcmp()" is used for the comparison. */ int sqliteSortCompare(const char *a, const char *b){ int len; int res = 0; int isNumA, isNumB; while( res==0 && *a && *b ){ assert( a[0]==b[0] ); if( a[1]==0 ){ res = -1; break; }else if( b[1]==0 ){ res = +1; break; } if( a[0]=='A' || a[0]=='D' ){ res = strcmp(&a[1],&b[1]); if( res ) break; }else{ isNumA = sqliteIsNumber(&a[1]); isNumB = sqliteIsNumber(&b[1]); if( isNumA ){ double rA, rB; if( !isNumB ){ res = -1; break; } rA = atof(&a[1]); rB = atof(&b[1]); if( rA<rB ){ res = -1; break; } if( rA>rB ){ res = +1; break; } }else if( isNumB ){ res = +1; break; }else{ res = sortStrCmp(&a[1],&b[1],0); if( res==0 ){ res = sortStrCmp(&a[1],&b[1],1); } if( res!=0 ){ break; } } } len = strlen(&a[1]) + 2; a += len; b += len; } if( *a=='-' || *a=='D' ) res = -res; return res; } /* ** Some powers of 64. These constants are needed in the ** sqliteRealToSortable() routine below. */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.164 2002/07/05 21:42:37 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
2628 2629 2630 2631 2632 2633 2634 | ** and the new key is pushed on top. If P2 is zero, the original ** data is popped off the stack first then the new key is pushed ** back in its place. ** ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the | | | 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 | ** and the new key is pushed on top. If P2 is zero, the original ** data is popped off the stack first then the new key is pushed ** back in its place. ** ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the ** stack. If P3 is NULL then all arguments are assumed to be numeric. ** ** See also: MakeIdxKey, SortMakeKey */ /* Opcode: MakeIdxKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. In addition, take one additional integer |
︙ | ︙ | |||
2657 2658 2659 2660 2661 2662 2663 | ** pushed on the stack. In other words, jump to P2 if the key is ** guaranteed to be unique. This jump can be used to skip a subsequent ** uniqueness test. ** ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the | | | 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 | ** pushed on the stack. In other words, jump to P2 if the key is ** guaranteed to be unique. This jump can be used to skip a subsequent ** uniqueness test. ** ** P3 is a string that is P1 characters long. Each character is either ** an 'n' or a 't' to indicates if the argument should be numeric or ** text. The first character corresponds to the lowest element on the ** stack. If P3 is null then all arguments are assumed to be numeric. ** ** See also: MakeKey, SortMakeKey */ case OP_MakeIdxKey: case OP_MakeKey: { char *zNewKey; int nByte; |
︙ | ︙ |
Changes to test/table.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # # $Id: table.test,v 1.18 2002/07/05 21:42:38 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a basic table and verify it is added to sqlite_master # do_test table-1.1 { |
︙ | ︙ | |||
430 431 432 433 434 435 436 | CREATE TABLE t6(a,b,c, FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED ); } } {0 {}} | > | > > > > > > > > > > | > > > > > > > > > > > > > > | 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 | CREATE TABLE t6(a,b,c, FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED ); } } {0 {}} # Test for the "typeof" function. # do_test table-11.1 { execsql { CREATE TABLE t7( a integer primary key, b number(5,10), c character varying (8), d VARCHAR(9), e clob, f BLOB, g Text, h ); INSERT INTO t7(a) VALUES(1); SELECT typeof(a), typeof(b), typeof(c), typeof(d), typeof(e), typeof(f), typeof(g), typeof(h) FROM t7 LIMIT 1; } } {numeric numeric text text text text text numeric} do_test table-11.2 { execsql { SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d) FROM t7 LIMIT 1; } } {numeric text numeric text} finish_test |