-C Do\snot\soverrun\sa\sbuffer\sin\sthe\sgenfkey\scode\s(now\spart\sof\sshell.c).\sFix\sfor\s#3722.\s(CVS\s6344)
-D 2009-03-13T15:32:53
+C Fix\sfor\s#3719.\sWhen\ssynthesizing\sa\sCREATE\sTABLE\sstatement\sas\sas\sresult\sof\sa\s"CREATE\sTABLE\sAS",\squote\sthe\scolumn\stype\snames\sunless\sthey\sare\ssimple\sidentifiers\sor\ssimple\sidentifiers\sfollowed\sby\sone\sor\stwo\sdimensions\s(e.g.\s"VARCHAR(10)").\s(CVS\s6345)
+D 2009-03-14T08:37:24
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in d64baddbf55cdf33ff030e14da837324711a4ef7
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/btree.c 6e7501d7a207dcc15b099e67231bc8cc86ef7fe9
F src/btree.h 96a019c9f28da38e79940512d7800e419cd8c702
F src/btreeInt.h 0a4884e6152d7cae9c741e91b830064c19fd2c05
-F src/build.c 741240c8d6a54201fa8757db1ee6efba71be59a2
+F src/build.c 7e5e93011bab2f142cb03faa72bb64ff30e321fc
F src/callback.c 09c6fedc77a45db99ba25a75d61382830314b357
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
F src/date.c 0d804df3bbda46329946a01ff5c75c3f4f135218
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
-F test/table.test 0aac9468b69d2683e68ee2682cdae28d82a453ec
+F test/table.test bf1bc3d9634342a3470bdf64b6190e7445b6b8a6
F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c
F test/tclsqlite.test 413a8a887d89ea8fa7055e8d118ffb03b0a4c91a
F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 03679857a320517a7b89e5214e948bce9af896a9
-R 6c05748751f4494b7f4484ee342f5594
+P 943b11fb188835f0c62b6064b084192b1bbe1c0c
+R 80daaf5cc0fe3707a03f09e098f3c65b
U danielk1977
-Z 81f620610e97249eb47012ea10670973
+Z e47d0a979c492c3c4fa5d4292c1f1fd6
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.521 2009/02/28 10:47:42 danielk1977 Exp $
+** $Id: build.c,v 1.522 2009/03/14 08:37:24 danielk1977 Exp $
*/
#include "sqliteInt.h"
}
/*
-** Write an identifier onto the end of the given string. Add
-** quote characters as needed.
+** This function is a wrapper around sqlite3GetToken() used by
+** isValidDimension(). This function differs from sqlite3GetToken() in
+** that:
+**
+** * Whitespace is ignored, and
+** * The output variable *peToken is set to 0 if the end of the
+** nul-terminated input string is reached.
+*/
+static int getTokenNoSpace(unsigned char *z, int *peToken){
+ int n = 0;
+ while( sqlite3Isspace(z[n]) ) n++;
+ if( !z[n] ){
+ *peToken = 0;
+ return 0;
+ }
+ return n + sqlite3GetToken(&z[n], peToken);
+}
+
+/*
+** Parameter z points to a nul-terminated string. Return true if, when
+** whitespace is ignored, the contents of this string matches one of
+** the following patterns:
+**
+** ""
+** "(number)"
+** "(number,number)"
*/
-static void identPut(char *z, int *pIdx, char *zSignedIdent){
+static int isValidDimension(unsigned char *z){
+ int eToken;
+ int n = 0;
+ n += getTokenNoSpace(&z[n], &eToken);
+ if( eToken ){
+ if( eToken!=TK_LP ) return 0;
+ n += getTokenNoSpace(&z[n], &eToken);
+ if( eToken==TK_PLUS || eToken==TK_MINUS ){
+ n += getTokenNoSpace(&z[n], &eToken);
+ }
+ if( eToken!=TK_INTEGER && eToken!=TK_FLOAT ) return 0;
+ n += getTokenNoSpace(&z[n], &eToken);
+ if( eToken==TK_COMMA ){
+ n += getTokenNoSpace(&z[n], &eToken);
+ if( eToken==TK_PLUS || eToken==TK_MINUS ){
+ n += getTokenNoSpace(&z[n], &eToken);
+ }
+ if( eToken!=TK_INTEGER && eToken!=TK_FLOAT ) return 0;
+ n += getTokenNoSpace(&z[n], &eToken);
+ }
+ if( eToken!=TK_RP ) return 0;
+ getTokenNoSpace(&z[n], &eToken);
+ }
+ if( eToken ) return 0;
+ return 1;
+}
+
+/*
+** The first parameter is a pointer to an output buffer. The second
+** parameter is a pointer to an integer that contains the offset at
+** which to write into the output buffer. This function copies the
+** nul-terminated string pointed to by the third parameter, zSignedIdent,
+** to the specified offset in the buffer and updates *pIdx to refer
+** to the first byte after the last byte written before returning.
+**
+** If the string zSignedIdent consists entirely of alpha-numeric
+** characters, does not begin with a digit and is not an SQL keyword,
+** then it is copied to the output buffer exactly as it is. Otherwise,
+** it is quoted using double-quotes.
+*/
+static void identPut(char *z, int *pIdx, char *zSignedIdent, int isTypename){
unsigned char *zIdent = (unsigned char*)zSignedIdent;
int i, j, needQuote;
i = *pIdx;
+
for(j=0; zIdent[j]; j++){
if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
}
- needQuote = zIdent[j]!=0 || sqlite3Isdigit(zIdent[0])
- || sqlite3KeywordCode(zIdent, j)!=TK_ID;
+ needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID;
+ if( !needQuote ){
+ if( isTypename ){
+ /* If this is a type-name, allow a little more flexibility. In SQLite,
+ ** a type-name is specified as:
+ **
+ ** ids [ids] [(number [, number])]
+ **
+ ** where "ids" is either a quoted string or a simple identifier (in the
+ ** above notation, [] means optional). It is a bit tricky to check
+ ** for all cases, but it is good to avoid unnecessarily quoting common
+ ** typenames like VARCHAR(10).
+ */
+ needQuote = !isValidDimension(&zIdent[j]);
+ }else{
+ needQuote = zIdent[j];
+ }
+ }
+
if( needQuote ) z[i++] = '"';
for(j=0; zIdent[j]; j++){
z[i++] = zIdent[j];
n += identLength(pCol->zName);
z = pCol->zType;
if( z ){
- n += (sqlite3Strlen30(z) + 1);
+ n += identLength(z);
}
}
n += identLength(p->zName);
}
sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
k = sqlite3Strlen30(zStmt);
- identPut(zStmt, &k, p->zName);
+ identPut(zStmt, &k, p->zName, 0);
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
sqlite3_snprintf(n-k, &zStmt[k], zSep);
k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
- identPut(zStmt, &k, pCol->zName);
+ identPut(zStmt, &k, pCol->zName, 0);
if( (z = pCol->zType)!=0 ){
zStmt[k++] = ' ';
assert( (int)(sqlite3Strlen30(z)+k+1)<=n );
- sqlite3_snprintf(n-k, &zStmt[k], "%s", z);
- k += sqlite3Strlen30(z);
+ identPut(zStmt, &k, z, 1);
}
}
sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE TABLE statement.
#
-# $Id: table.test,v 1.49 2009/01/16 11:04:58 danielk1977 Exp $
+# $Id: table.test,v 1.50 2009/03/14 08:37:24 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
}
} {1 {no such table: no_such_table}}
+do_test table-8.9 {
+ execsql {
+ CREATE TABLE t10("col.1" [char.3]);
+ CREATE TABLE t11 AS SELECT * FROM t10;
+ SELECT sql FROM sqlite_master WHERE name = 't11';
+ }
+} {{CREATE TABLE t11("col.1" "char.3")}}
+do_test table-8.10 {
+ execsql {
+ CREATE TABLE t12(
+ a INTEGER,
+ b VARCHAR(10),
+ c VARCHAR(1,10),
+ d VARCHAR(+1,-10),
+ e VARCHAR (+1,-10),
+ f "VARCHAR (+1,-10, 5)",
+ g BIG INTEGER
+ );
+ CREATE TABLE t13 AS SELECT * FROM t12;
+ SELECT sql FROM sqlite_master WHERE name = 't13';
+ }
+} {{CREATE TABLE t13(
+ a INTEGER,
+ b VARCHAR(10),
+ c VARCHAR(1,10),
+ d VARCHAR(+1,-10),
+ e VARCHAR (+1,-10),
+ f "VARCHAR (+1,-10, 5)",
+ g "BIG INTEGER"
+)}}
+
# Make sure we cannot have duplicate column names within a table.
#
do_test table-9.1 {