Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | When expanding '*' in the result set of a SELECT, quote the expanded identifiers. Fix for #2450. (CVS 4111) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d5b7224f37db1729dd042d48765d7a79 |
User & Date: | danielk1977 2007-06-24 06:32:18.000 |
Context
2007-06-24
| ||
08:00 | Add the "(database.)freelist_count" PRAGMA. For querying the size of the database free-list. (CVS 4112) (check-in: 1fb4251a70 user: danielk1977 tags: trunk) | |
06:32 | When expanding '*' in the result set of a SELECT, quote the expanded identifiers. Fix for #2450. (CVS 4111) (check-in: d5b7224f37 user: danielk1977 tags: trunk) | |
2007-06-22
| ||
20:17 | fix linking failure on OS/2 that happens with the amalgamation and the high memory option enabled (CVS 4110) (check-in: f35e20e196 user: pweilbacher tags: trunk) | |
Changes
Changes to src/printf.c.
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #define etCHARLIT 10 /* Literal characters. %' */ #define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */ #define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ #define etTOKEN 13 /* a pointer to a Token structure */ #define etSRCLIST 14 /* a pointer to a SrcList */ #define etPOINTER 15 /* The %p conversion */ /* ** An "etByte" is an 8-bit unsigned value. */ typedef unsigned char etByte; | > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #define etCHARLIT 10 /* Literal characters. %' */ #define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */ #define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ #define etTOKEN 13 /* a pointer to a Token structure */ #define etSRCLIST 14 /* a pointer to a SrcList */ #define etPOINTER 15 /* The %p conversion */ #define etSQLESCAPE3 16 /* %w -> Strings with '\"' doubled */ /* ** An "etByte" is an 8-bit unsigned value. */ typedef unsigned char etByte; |
︙ | ︙ | |||
111 112 113 114 115 116 117 118 119 120 121 122 123 124 | static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 }, { 'z', 0, 6, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, { 'u', 10, 0, etRADIX, 0, 0 }, { 'x', 16, 0, etRADIX, 16, 1 }, { 'X', 16, 0, etRADIX, 0, 4 }, #ifndef SQLITE_OMIT_FLOATING_POINT { 'f', 0, 1, etFLOAT, 0, 0 }, | > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 }, { 'z', 0, 6, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, 0, 2 }, { 'u', 10, 0, etRADIX, 0, 0 }, { 'x', 16, 0, etRADIX, 16, 1 }, { 'X', 16, 0, etRADIX, 0, 4 }, #ifndef SQLITE_OMIT_FLOATING_POINT { 'f', 0, 1, etFLOAT, 0, 0 }, |
︙ | ︙ | |||
607 608 609 610 611 612 613 | }else if( xtype==etDYNSTRING ){ zExtra = bufpt; } length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; case etSQLESCAPE: | > | > | | | | | 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 644 645 646 647 648 | }else if( xtype==etDYNSTRING ){ zExtra = bufpt; } length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; case etSQLESCAPE: case etSQLESCAPE2: case etSQLESCAPE3: { int i, j, n, ch, isnull; int needQuote; char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ char *escarg = va_arg(ap,char*); isnull = escarg==0; if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); for(i=n=0; (ch=escarg[i])!=0; i++){ if( ch==q ) n++; } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqliteMalloc( n ); if( bufpt==0 ) return -1; }else{ bufpt = buf; } j = 0; if( needQuote ) bufpt[j++] = q; for(i=0; (ch=escarg[i])!=0; i++){ bufpt[j++] = ch; if( ch==q ) bufpt[j++] = ch; } if( needQuote ) bufpt[j++] = q; bufpt[j] = 0; length = j; /* The precision is ignored on %q and %Q */ /* if( precision>=0 && precision<length ) length = precision; */ break; } case etTOKEN: { |
︙ | ︙ |
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.352 2007/06/24 06:32:18 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
180 181 182 183 184 185 186 187 188 189 190 191 192 193 | ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ p->z = (u8*)z; p->n = z ? strlen(z) : 0; p->dyn = 0; } /* ** Create an expression node for an identifier with the name of zName */ Expr *sqlite3CreateIdExpr(const char *zName){ Token dummy; setToken(&dummy, zName); | > > > > > > > > > > > > > > | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | ** Set the value of a token to a '\000'-terminated string. */ static void setToken(Token *p, const char *z){ p->z = (u8*)z; p->n = z ? strlen(z) : 0; p->dyn = 0; } /* ** Set the token to the double-quoted and escaped version of the string pointed ** to by z. For example; ** ** {a"bc} -> {"a""bc"} */ static void setQuotedToken(Token *p, const char *z){ p->z = (u8 *)sqlite3MPrintf("\"%w\"", z); p->dyn = 1; if( p->z ){ p->n = strlen((char *)p->z); } } /* ** Create an expression node for an identifier with the name of zName */ Expr *sqlite3CreateIdExpr(const char *zName){ Token dummy; setToken(&dummy, zName); |
︙ | ︙ | |||
1332 1333 1334 1335 1336 1337 1338 | /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(TK_ID, 0, 0, 0); if( pRight==0 ) break; | | | > | 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 | /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(TK_ID, 0, 0, 0); if( pRight==0 ) break; setQuotedToken(&pRight->token, zName); if( zTabName && (longNames || pTabList->nSrc>1) ){ Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0); pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); if( pExpr==0 ) break; setQuotedToken(&pLeft->token, zTabName); setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName)); pExpr->span.dyn = 1; pExpr->token.z = 0; pExpr->token.n = 0; pExpr->token.dyn = 0; }else{ pExpr = pRight; pExpr->span = pExpr->token; pExpr->span.dyn = 0; } if( longNames ){ pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span); }else{ pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token); } } |
︙ | ︙ | |||
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 | } sqlite3ExprListDelete(pEList); p->pEList = pNew; } if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); rc = SQLITE_ERROR; } return rc; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine associates entries in an ORDER BY expression list with | > > > | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 | } sqlite3ExprListDelete(pEList); p->pEList = pNew; } if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); rc = SQLITE_ERROR; } if( sqlite3MallocFailed() ){ rc = SQLITE_NOMEM; } return rc; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine associates entries in an ORDER BY expression list with |
︙ | ︙ |
Added test/tkt2450.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 | # 2007 June 24 # # 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 is to test that ticket #2450 has been fixed. # # $Id: tkt2450.test,v 1.1 2007/06/24 06:32:18 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt2450-1 { execsql { CREATE TABLE "t a" ("""cb"""); INSERT INTO "t a" ("""cb""") VALUES (1); SELECT """cb""" FROM "t a"; } } {1} do_test tkt2450-2 { execsql { SELECT * FROM "t a"; } } {1} do_test tkt2450-3 { execsql { SELECT "t a".* FROM "t a"; } } {1} do_test tkt2450-3 { execsql { CREATE TABLE t1(a); INSERT INTO t1 VALUES(2); SELECT * FROM "t a", t1; } } {1 2} finish_test |