Fix the schemalint.tcl script to handle identifiers that require quoting.

FossilOrigin-Name: 451e0fafbe5b7e9c67d9b584d5e16796c3196881
This commit is contained in:
dan 2015-11-30 18:17:55 +00:00
parent 323f7d3fc6
commit c45bf341af
5 changed files with 143 additions and 33 deletions

View File

@ -1,5 +1,5 @@
C In\sthe\sCREATE\sINDEX\sstatements\soutput\sby\sschemalint.tcl,\savoid\sdeclaring\san\sexplicit\scollation\ssequence\sthat\sis\sthe\ssame\sas\sthe\scolumn's\sdefault.
D 2015-11-23T18:28:07.584
C Fix\sthe\sschemalint.tcl\sscript\sto\shandle\sidentifiers\sthat\srequire\squoting.
D 2015-11-30T18:17:55.036
F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc e928e68168df69b353300ac87c10105206653a03
@ -416,7 +416,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 18b0ed49830cf04fe2d68224b41838a73ac6cd24
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba
F src/where.c 5804902239731a7025240f4338d98cdc57315636
F src/where.c be09f4a0513f885845ae481324c2e07603f88b38
F src/whereInt.h 7892bb54cf9ca0ae5c7e6094491b94c9286dc647
F src/wherecode.c 4c96182e7b25e4be54008dee2da5b9c2f8480b9b
F src/whereexpr.c bd4877cd4dd11f6ab551ef0054535ca3c6224950
@ -973,7 +973,7 @@ F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
F test/schemalint.test 7fba0e262353c8c3dd5ee406cb11cf90f8b566fe
F test/schemalint.test cee9f375637fcc8c6e77d971abe044445c23e024
F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
@ -1381,7 +1381,7 @@ F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a
F tool/schemalint.tcl ad61083d39cb40e848b9acc1273e4c487bb55cd7
F tool/schemalint.tcl 2f44d0874061a948f6ef53505062db4ac9806cf7
F tool/showdb.c d4476e000a64eca9f5e2c2f68741e747b9778e8d
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
@ -1406,7 +1406,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 8f1ef0904d055b5510ec9043810ebf22a8c5e253
R 4b9b445c1607ad5c9f9bdcf33b4eb416
P d3aa067c830e98f2074630c4613c557b0ce90a57
R aed657578ea11902053a31be3048325d
U dan
Z 6d9149db2c512107280c4e32c490b8cb
Z 94438cf65b515737c9a10851485e87ac

View File

@ -1 +1 @@
d3aa067c830e98f2074630c4613c557b0ce90a57
451e0fafbe5b7e9c67d9b584d5e16796c3196881

View File

@ -3942,7 +3942,8 @@ static char *whereAppendSingleTerm(
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
if( zOp ){
const char *zFmt = bOr ? "%z{{%s %s %s %lld}}" : "%z{%s %s %s %lld}";
const char *zFmt = bOr ? "%z{{%s \"%w\" \"%w\" %lld}}" :
"%z{%s \"%w\" \"%w\" %lld}";
zBuf = whereAppendPrintf(db, zFmt, zIn,
zOp, pTab->aCol[pTerm->u.leftColumn].zName,
(pColl ? pColl->zName : "BINARY"),
@ -4025,7 +4026,7 @@ static void whereTraceBuilder(
nCol = pTab->nCol;
/* Append the table name to the buffer. */
zBuf = whereAppendPrintf(db, "%s", pTab->zName);
zBuf = whereAppendPrintf(db, "\"%w\"", pTab->zName);
/* Append the list of columns required to create a covering index */
zBuf = whereAppendPrintf(db, "%z {cols", zBuf);
@ -4033,7 +4034,8 @@ static void whereTraceBuilder(
for(iCol=0; iCol<nCol; iCol++){
if( iCol==(sizeof(Bitmask)*8-1) ) break;
if( pItem->colUsed & ((u64)1 << iCol) ){
zBuf = whereAppendPrintf(db, "%z %s", zBuf, pTab->aCol[iCol].zName);
const char *zName = pTab->aCol[iCol].zName;
zBuf = whereAppendPrintf(db, "%z \"%w\"", zBuf, zName);
}
}
}
@ -4054,7 +4056,7 @@ static void whereTraceBuilder(
if( pExpr->op==TK_COLUMN && pExpr->iTable==pItem->iCursor ){
if( pExpr->iColumn>=0 ){
const char *zName = pTab->aCol[pExpr->iColumn].zName;
zBuf = whereAppendPrintf(db, "%z%s%s %s %s", zBuf,
zBuf = whereAppendPrintf(db, "%z%s\"%w\" \"%w\" %s", zBuf,
bFirst ? " {orderby " : " ", zName, pColl->zName,
(pOrderBy->a[i].sortOrder ? "DESC" : "ASC")
);

View File

@ -27,33 +27,33 @@ do_execsql_test 1.0 {
do_trace_test 1.1 {
SELECT b, c, y, z FROM t1, t2 WHERE c=? AND z=?
} {
{t1 {cols b c} {eq c BINARY 0}}
{t2 {cols y z} {eq z BINARY 0}}
{"t1" {cols "b" "c"} {eq "c" "BINARY" 0}}
{"t2" {cols "y" "z"} {eq "z" "BINARY" 0}}
}
do_trace_test 1.2 {
SELECT a FROM t1 WHERE b>10
} {
{t1 {cols a b} {range b BINARY 0}}
{"t1" {cols "a" "b"} {range "b" "BINARY" 0}}
}
do_trace_test 1.3 {
SELECT b FROM t1 WHERE b IN (10, 20, 30)
} {
{t1 {cols b} {eq b BINARY 0}}
{"t1" {cols "b"} {eq "b" "BINARY" 0}}
}
do_trace_test 1.4 {
SELECT * FROM t1, t2 WHERE x=a
} {
{t1 {cols a b c} {eq a BINARY 2}}
{t2 {cols x y z} {eq x BINARY 1}}
{"t1" {cols "a" "b" "c"} {eq "a" "BINARY" 2}}
{"t2" {cols "x" "y" "z"} {eq "x" "BINARY" 1}}
}
do_trace_test 1.5 {
SELECT * FROM t1 WHERE a IN (1, 2, 3)
} {
{t1 {cols a b c} {eq a BINARY 0}}
{"t1" {cols "a" "b" "c"} {eq "a" "BINARY" 0}}
}
#-----------------------------------------------------------------------
@ -62,19 +62,19 @@ do_trace_test 1.5 {
do_trace_test 2.1 {
SELECT * FROM t1 WHERE a=? OR b=?
} {
{t1 {cols a b c} {or {{eq a BINARY 0}} {{eq b BINARY 0}}}}
{"t1" {cols "a" "b" "c"} {or {{eq "a" "BINARY" 0}} {{eq "b" "BINARY" 0}}}}
}
do_trace_test 2.2 {
SELECT * FROM t1 WHERE a=? OR (b=? AND c=?)
} {
{t1 {cols a b c} {or {{eq a BINARY 0}} {{eq b BINARY 0} {eq c BINARY 0}}}}
{"t1" {cols "a" "b" "c"} {or {{eq "a" "BINARY" 0}} {{eq "b" "BINARY" 0} {eq "c" "BINARY" 0}}}}
}
do_trace_test 2.3 {
SELECT * FROM t1 WHERE (a=? AND b=?) OR c=?
} {
{t1 {cols a b c} {or {{eq c BINARY 0}} {{eq a BINARY 0} {eq b BINARY 0}}}}
{"t1" {cols "a" "b" "c"} {or {{eq "c" "BINARY" 0}} {{eq "a" "BINARY" 0} {eq "b" "BINARY" 0}}}}
}
#-----------------------------------------------------------------------
@ -82,19 +82,19 @@ do_trace_test 2.3 {
#
do_trace_test 3.1 {
SELECT * FROM t1 ORDER BY a;
} {{t1 {cols a b c} {orderby a BINARY ASC}}}
} {{"t1" {cols "a" "b" "c"} {orderby "a" "BINARY" ASC}}}
do_trace_test 3.2 {
SELECT * FROM t1 WHERE a=? ORDER BY b;
} {{t1 {cols a b c} {eq a BINARY 0} {orderby b BINARY ASC}}}
} {{"t1" {cols "a" "b" "c"} {eq "a" "BINARY" 0} {orderby "b" "BINARY" ASC}}}
do_trace_test 3.3 {
SELECT min(a) FROM t1;
} {{t1 {cols a} {orderby a BINARY ASC}}}
} {{"t1" {cols "a"} {orderby "a" "BINARY" ASC}}}
do_trace_test 3.4 {
SELECT max(a) FROM t1;
} {{t1 {cols a} {orderby a BINARY DESC}}}
} {{"t1" {cols "a"} {orderby "a" "BINARY" DESC}}}
finish_test

View File

@ -11,6 +11,41 @@ proc usage {} {
exit
}
# Return the quoted version of identfier $id. Quotes are only added if
# they are required by SQLite.
#
# This command currently assumes that quotes are required if the
# identifier contains any ASCII-range characters that are not
# alpha-numeric or underscores.
#
proc quote {id} {
if {[requires_quote $id]} {
set x [string map {\" \"\"} $id]
return "\"$x\""
}
return $id
}
proc requires_quote {id} {
foreach c [split $id {}] {
if {[string is alnum $c]==0 && $c!="_"} {
return 1
}
}
return 0
}
# The argument passed to this command is a Tcl list of identifiers. The
# value returned is the same list, except with each item quoted and the
# elements comma-separated.
#
proc list_to_sql {L} {
set ret [list]
foreach l $L {
lappend ret [quote $l]
}
join $ret ", "
}
proc process_cmdline_args {ctxvar argv} {
upvar $ctxvar G
set nArg [llength $argv]
@ -139,11 +174,11 @@ proc eqset_to_index {ctxvar aCollVar tname eqset {range {}}} {
foreach {c collate dir} $rangeset {
append idxname "_$c"
set coldef $c
set coldef [quote $c]
if {[string compare -nocase $collate $aColl($c)]!=0} {
append idxname [string tolower $collate]
append coldef " COLLATE $collate"
append coldef " COLLATE [quote $collate]"
}
if {$dir=="DESC"} {
@ -153,7 +188,7 @@ proc eqset_to_index {ctxvar aCollVar tname eqset {range {}}} {
lappend lCols $coldef
}
set create_index "CREATE INDEX $idxname ON ${tname}("
set create_index "CREATE INDEX [quote $idxname] ON [quote $tname]("
append create_index [join $lCols ", "]
append create_index ");"
@ -185,12 +220,27 @@ proc expand_or_cons {L} {
return $lRet
}
#--------------------------------------------------------------------------
# Argument $tname is the name of a table in the main database opened by
# database handle [db]. $arrayvar is the name of an array variable in the
# caller's context. This command populates the array with an entry mapping
# from column name to default collation sequence for each column of table
# $tname. For example, if a table is declared:
#
# CREATE TABLE t1(a COLLATE nocase, b, c COLLATE binary)
#
# the mapping is populated with:
#
# map(a) -> "nocase"
# map(b) -> "binary"
# map(c) -> "binary"
#
proc sqlidx_get_coll_map {tname arrayvar} {
upvar $arrayvar aColl
set colnames [list]
db eval "PRAGMA table_info = $tname" x { lappend colnames $x(name) }
db eval "CREATE INDEX schemalint_test ON ${tname}([join $colnames ,])"
set qname [quote $tname]
db eval "PRAGMA table_info = $qname" x { lappend colnames $x(name) }
db eval "CREATE INDEX schemalint_test ON ${qname}([list_to_sql $colnames])"
db eval "PRAGMA index_xinfo = schemalint_test" x {
set aColl($x(name)) $x(coll)
}
@ -348,6 +398,7 @@ proc sqlidx_one_test {tn schema select expected} {
sqlidx_init_context C
sqlite3 db ""
db collate "a b c" [list string compare]
db eval $schema
lappend C(lSelect) $select
analyze_selects C
@ -362,9 +413,14 @@ proc sqlidx_one_test {tn schema select expected} {
}
db close
upvar nTest nTest
incr nTest
}
proc sqlidx_internal_tests {} {
set nTest 0
# No indexes for a query with no constraints.
sqlidx_one_test 0 {
@ -440,6 +496,58 @@ proc sqlidx_internal_tests {} {
{CREATE INDEX t1_a ON t1(a);}
}
# Tables with names that require quotes.
#
sqlidx_one_test 8.1 {
CREATE TABLE "t t"(a, b, c);
} {
SELECT * FROM "t t" WHERE a=?
} {
{CREATE INDEX "t t_a" ON "t t"(a);}
}
sqlidx_one_test 8.2 {
CREATE TABLE "t t"(a, b, c);
} {
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
} {
{CREATE INDEX "t t_b" ON "t t"(b);}
}
# Columns with names that require quotes.
#
sqlidx_one_test 9.1 {
CREATE TABLE t3(a, "b b", c);
} {
SELECT * FROM t3 WHERE "b b" = ?
} {
{CREATE INDEX "t3_b b" ON t3("b b");}
}
sqlidx_one_test 9.2 {
CREATE TABLE t3(a, "b b", c);
} {
SELECT * FROM t3 ORDER BY "b b"
} {
{CREATE INDEX "t3_b b" ON t3("b b");}
}
# Collations with names that require quotes.
#
sqlidx_one_test 10.1 {
CREATE TABLE t4(a, b, c);
} {
SELECT * FROM t4 ORDER BY c COLLATE "a b c"
} {
{CREATE INDEX "t4_ca b c" ON t4(c COLLATE "a b c");}
}
sqlidx_one_test 10.2 {
CREATE TABLE t4(a, b, c);
} {
SELECT * FROM t4 WHERE c = ? COLLATE "a b c"
} {
{CREATE INDEX "t4_ca b c" ON t4(c COLLATE "a b c");}
}
puts "All $nTest tests passed"
exit
}
# End of internal test code.