mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
When expanding '*' in the result set of a SELECT, quote the expanded identifiers. Fix for #2450. (CVS 4111)
FossilOrigin-Name: d5b7224f37db1729dd042d48765d7a79247e1bde
This commit is contained in:
17
manifest
17
manifest
@@ -1,5 +1,5 @@
|
|||||||
C fix\slinking\sfailure\son\sOS/2\sthat\shappens\swith\sthe\samalgamation\sand\sthe\shigh\smemory\soption\senabled\s(CVS\s4110)
|
C When\sexpanding\s'*'\sin\sthe\sresult\sset\sof\sa\sSELECT,\squote\sthe\sexpanded\sidentifiers.\sFix\sfor\s#2450.\s(CVS\s4111)
|
||||||
D 2007-06-22T20:17:38
|
D 2007-06-24T06:32:18
|
||||||
F Makefile.in 7f7485a4cc039476a42e534b3f26ec90e2f9753e
|
F Makefile.in 7f7485a4cc039476a42e534b3f26ec90e2f9753e
|
||||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@@ -101,9 +101,9 @@ F src/pager.h 94110a5570dca30d54a883e880a3633b2e4c05ae
|
|||||||
F src/parse.y ad2ce25665be7f7303137f774a4e3e72e0d036ff
|
F src/parse.y ad2ce25665be7f7303137f774a4e3e72e0d036ff
|
||||||
F src/pragma.c 0d25dad58bdfd6789943a10f1b9663c2eb85b96d
|
F src/pragma.c 0d25dad58bdfd6789943a10f1b9663c2eb85b96d
|
||||||
F src/prepare.c 87c23644986b5e41a58bc76f05abebd899e00089
|
F src/prepare.c 87c23644986b5e41a58bc76f05abebd899e00089
|
||||||
F src/printf.c deaef57ea97557b8b53313d5c793fa4236036a0e
|
F src/printf.c 9b3048d270e8bb2f8b910b491ac3aadece6cfab2
|
||||||
F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
||||||
F src/select.c 33a258fc9c9dccb28ae2d3a02f1e1148d6433148
|
F src/select.c 2ee53f929fe3755a35de1fb937f22e2e60f7d3e5
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 4b0fc3c76a9f23a1c963e01703c0fbbca1b5c34d
|
F src/shell.c 4b0fc3c76a9f23a1c963e01703c0fbbca1b5c34d
|
||||||
F src/sqlite.h.in 6f290b660b2e7c3359968bb4b344ec31a1178746
|
F src/sqlite.h.in 6f290b660b2e7c3359968bb4b344ec31a1178746
|
||||||
@@ -396,6 +396,7 @@ F test/tkt2332.test cb1bb0ed1ae6a3b9ff412520ed4a496745f4ffa5
|
|||||||
F test/tkt2339.test 7016415bda86af1406a27260ac46f44885617606
|
F test/tkt2339.test 7016415bda86af1406a27260ac46f44885617606
|
||||||
F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567
|
F test/tkt2391.test ab7a11be7402da8b51a5be603425367aa0684567
|
||||||
F test/tkt2409.test f130054aedff681883466ad04332bd3f7db51a02
|
F test/tkt2409.test f130054aedff681883466ad04332bd3f7db51a02
|
||||||
|
F test/tkt2450.test 77ed94863f2049c1420288ddfea2d41e5e0971d6
|
||||||
F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
|
F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
|
||||||
F test/trans.test 9e6e7b886ea8093239801b5af0981ff784d9c541
|
F test/trans.test 9e6e7b886ea8093239801b5af0981ff784d9c541
|
||||||
F test/trigger1.test b361161cf20614024cc1e52ea0bdec250776b2ae
|
F test/trigger1.test b361161cf20614024cc1e52ea0bdec250776b2ae
|
||||||
@@ -512,7 +513,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 12327ca049e62922bfb3c2a14e42554fd58265e8
|
P f35e20e19633d7b114fdf145820ca5d61b5aa925
|
||||||
R c4f5686bdc00846759c01fbdffa7f82b
|
R 0028662710d587da4e5d82de686d252d
|
||||||
U pweilbacher
|
U danielk1977
|
||||||
Z bbe405d266119d64ef43df21e50d3180
|
Z 13d4831b99a0601e7fdfc2a1c76b4c67
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
f35e20e19633d7b114fdf145820ca5d61b5aa925
|
d5b7224f37db1729dd042d48765d7a79247e1bde
|
||||||
14
src/printf.c
14
src/printf.c
@@ -74,6 +74,7 @@
|
|||||||
#define etTOKEN 13 /* a pointer to a Token structure */
|
#define etTOKEN 13 /* a pointer to a Token structure */
|
||||||
#define etSRCLIST 14 /* a pointer to a SrcList */
|
#define etSRCLIST 14 /* a pointer to a SrcList */
|
||||||
#define etPOINTER 15 /* The %p conversion */
|
#define etPOINTER 15 /* The %p conversion */
|
||||||
|
#define etSQLESCAPE3 16 /* %w -> Strings with '\"' doubled */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -115,6 +116,7 @@ static const et_info fmtinfo[] = {
|
|||||||
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
|
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
|
||||||
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
|
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
|
||||||
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
|
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
|
||||||
|
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
|
||||||
{ 'c', 0, 0, etCHARX, 0, 0 },
|
{ 'c', 0, 0, etCHARX, 0, 0 },
|
||||||
{ 'o', 8, 0, etRADIX, 0, 2 },
|
{ 'o', 8, 0, etRADIX, 0, 2 },
|
||||||
{ 'u', 10, 0, etRADIX, 0, 0 },
|
{ 'u', 10, 0, etRADIX, 0, 0 },
|
||||||
@@ -611,14 +613,16 @@ static int vxprintf(
|
|||||||
if( precision>=0 && precision<length ) length = precision;
|
if( precision>=0 && precision<length ) length = precision;
|
||||||
break;
|
break;
|
||||||
case etSQLESCAPE:
|
case etSQLESCAPE:
|
||||||
case etSQLESCAPE2: {
|
case etSQLESCAPE2:
|
||||||
|
case etSQLESCAPE3: {
|
||||||
int i, j, n, ch, isnull;
|
int i, j, n, ch, isnull;
|
||||||
int needQuote;
|
int needQuote;
|
||||||
|
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
|
||||||
char *escarg = va_arg(ap,char*);
|
char *escarg = va_arg(ap,char*);
|
||||||
isnull = escarg==0;
|
isnull = escarg==0;
|
||||||
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
||||||
for(i=n=0; (ch=escarg[i])!=0; i++){
|
for(i=n=0; (ch=escarg[i])!=0; i++){
|
||||||
if( ch=='\'' ) n++;
|
if( ch==q ) n++;
|
||||||
}
|
}
|
||||||
needQuote = !isnull && xtype==etSQLESCAPE2;
|
needQuote = !isnull && xtype==etSQLESCAPE2;
|
||||||
n += i + 1 + needQuote*2;
|
n += i + 1 + needQuote*2;
|
||||||
@@ -629,12 +633,12 @@ static int vxprintf(
|
|||||||
bufpt = buf;
|
bufpt = buf;
|
||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
if( needQuote ) bufpt[j++] = '\'';
|
if( needQuote ) bufpt[j++] = q;
|
||||||
for(i=0; (ch=escarg[i])!=0; i++){
|
for(i=0; (ch=escarg[i])!=0; i++){
|
||||||
bufpt[j++] = ch;
|
bufpt[j++] = ch;
|
||||||
if( ch=='\'' ) bufpt[j++] = ch;
|
if( ch==q ) bufpt[j++] = ch;
|
||||||
}
|
}
|
||||||
if( needQuote ) bufpt[j++] = '\'';
|
if( needQuote ) bufpt[j++] = q;
|
||||||
bufpt[j] = 0;
|
bufpt[j] = 0;
|
||||||
length = j;
|
length = j;
|
||||||
/* The precision is ignored on %q and %Q */
|
/* The precision is ignored on %q and %Q */
|
||||||
|
|||||||
24
src/select.c
24
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.351 2007/06/15 15:31:50 drh Exp $
|
** $Id: select.c,v 1.352 2007/06/24 06:32:18 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -185,6 +185,20 @@ static void setToken(Token *p, const char *z){
|
|||||||
p->dyn = 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
|
** Create an expression node for an identifier with the name of zName
|
||||||
*/
|
*/
|
||||||
@@ -1336,12 +1350,12 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
|||||||
}
|
}
|
||||||
pRight = sqlite3Expr(TK_ID, 0, 0, 0);
|
pRight = sqlite3Expr(TK_ID, 0, 0, 0);
|
||||||
if( pRight==0 ) break;
|
if( pRight==0 ) break;
|
||||||
setToken(&pRight->token, zName);
|
setQuotedToken(&pRight->token, zName);
|
||||||
if( zTabName && (longNames || pTabList->nSrc>1) ){
|
if( zTabName && (longNames || pTabList->nSrc>1) ){
|
||||||
Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
|
Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
|
||||||
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
|
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
|
||||||
if( pExpr==0 ) break;
|
if( pExpr==0 ) break;
|
||||||
setToken(&pLeft->token, zTabName);
|
setQuotedToken(&pLeft->token, zTabName);
|
||||||
setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName));
|
setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName));
|
||||||
pExpr->span.dyn = 1;
|
pExpr->span.dyn = 1;
|
||||||
pExpr->token.z = 0;
|
pExpr->token.z = 0;
|
||||||
@@ -1350,6 +1364,7 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
|||||||
}else{
|
}else{
|
||||||
pExpr = pRight;
|
pExpr = pRight;
|
||||||
pExpr->span = pExpr->token;
|
pExpr->span = pExpr->token;
|
||||||
|
pExpr->span.dyn = 0;
|
||||||
}
|
}
|
||||||
if( longNames ){
|
if( longNames ){
|
||||||
pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
|
pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
|
||||||
@@ -1376,6 +1391,9 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
|||||||
sqlite3ErrorMsg(pParse, "too many columns in result set");
|
sqlite3ErrorMsg(pParse, "too many columns in result set");
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
if( sqlite3MallocFailed() ){
|
||||||
|
rc = SQLITE_NOMEM;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
test/tkt2450.test
Normal file
48
test/tkt2450.test
Normal file
@@ -0,0 +1,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
|
||||||
Reference in New Issue
Block a user