]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework the logic that generates a schema for tables created using
authordrh <drh@noemail.net>
Mon, 11 May 2009 20:53:28 +0000 (20:53 +0000)
committerdrh <drh@noemail.net>
Mon, 11 May 2009 20:53:28 +0000 (20:53 +0000)
"CREATE TABLE ... AS SELECT ...".  Instead of trying to copy the raw
datatype string from the right-hand side, just make the type one
of TEXT, INT, REAL, NUM, or nothing.  This is much simpler than
trying to parse and quote datatype strings.  Other minor
implifications to build.c are bundled with this change. (CVS 6626)

FossilOrigin-Name: 33cf83591e6e13875ef6ada5b8ac8ab07619d8bc

manifest
manifest.uuid
src/build.c
src/callback.c
src/expr.c
src/main.c
src/prepare.c
src/select.c
src/sqliteInt.h
test/table.test

index 4fe50d4bc53bf9b9b3dd1969e1a568bf0fbf3d86..3f4ad383fa6c2051bcde0d2faa80447f0c8ae03a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthe\sparser\sto\sallow\snested\sparentheses\sin\sthe\smodule\sargument\sof\na\sCREATE\sVIRTUAL\sTABLE\sstatement.\s(CVS\s6625)
-D 2009-05-11T18:22:31
+C Rework\sthe\slogic\sthat\sgenerates\sa\sschema\sfor\stables\screated\susing\r\n"CREATE\sTABLE\s...\sAS\sSELECT\s...".\s\sInstead\sof\strying\sto\scopy\sthe\sraw\r\ndatatype\sstring\sfrom\sthe\sright-hand\sside,\sjust\smake\sthe\stype\sone\s\r\nof\sTEXT,\sINT,\sREAL,\sNUM,\sor\snothing.\s\sThis\sis\smuch\ssimpler\sthan\s\r\ntrying\sto\sparse\sand\squote\sdatatype\sstrings.\s\sOther\sminor\s\r\nimplifications\sto\sbuild.c\sare\sbundled\swith\sthis\schange.\s(CVS\s6626)
+D 2009-05-11T20:53:29
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -109,12 +109,12 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
 F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c
 F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd
 F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
-F src/build.c a8320b5fe742dcae98c8f7315b59d61e8e642a4d
-F src/callback.c c54a923b06a17a2f965e5c3a6f87a3a963209a4c
+F src/build.c caece8163ad2cf6be278ad5405f25852c468d8d8
+F src/callback.c bf295cfdc065b56cc49a5f6452126dc4ffe0ff5b
 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
 F src/delete.c a0a0932eea77471ab243337026abbce444024c43
-F src/expr.c d2297420722d6ce17f967f22401233b3af878bb3
+F src/expr.c 79f1cb93526a5f64625b7979893e506012fe26d7
 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
 F src/func.c f667fe886309707c7178542073bb0ced00a9fae7
 F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
@@ -125,7 +125,7 @@ F src/insert.c 050536ea91c6cf74d87a2386b5da241141943c94
 F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
 F src/legacy.c 9a56cf126ceee332b56061bf16bd0fb4ff9e26c0
 F src/loadext.c 3f96631089fc4f3871a67f02f2e4fc7ea4d51edc
-F src/main.c eabeb200c8b74e0d117d37474b642eb286ebfd93
+F src/main.c e557fd8f721373b863c1a804aa8ea81839541d27
 F src/malloc.c 7b3b6423f5b355e5d649b91e16ef252d610bcf19
 F src/mem0.c f2f84062d1f35814d6535c9f9e33de3bfb3b132c
 F src/mem1.c e6d5c23941288df8191b8a98c28e3f57771e2270
@@ -153,16 +153,16 @@ F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d
 F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
 F src/pcache1.c a6138ee57da3259149ca5254e0156d9b624db850
 F src/pragma.c c26c16c49a80d03c8597f0e6c7daba53f283428f
-F src/prepare.c 72d74e6d3b9c8eb0663b33ec6438aa718096ac79
+F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839
 F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456
 F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
 F src/resolve.c 2ce8f8bc8a0c913cbaec3fb3da2be113ea1fa5af
 F src/rowset.c 14d12b5e81b5907b87d511f6f4219805f96a4b55
-F src/select.c 9587023e906afe2074a718d25d6a4326874fb791
+F src/select.c 2877098ffabd751c274aa5f993d515484d955896
 F src/shell.c 0a11f831603f17fea20ca97133c0f64e716af4a7
 F src/sqlite.h.in d028ed6e0e991d730644f0b418964df1b51e6c53
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 04607d0bee31fdbebf133cf6c764cfc3b447e340
+F src/sqliteInt.h 0a39cbf63cc7fe54aa9a4bb053e21b5b5b7cde14
 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@@ -559,7 +559,7 @@ F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
 F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
 F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
 F test/sync.test ded6b39d8d8ca3c0c5518516c6371b3316d3e3a3
-F test/table.test e47c9323396976389a15fa0cd22ce3a405433186
+F test/table.test 00fe72cef1851c693d996433b993423a9a607247
 F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c
 F test/tclsqlite.test 8b1150d0486c4848c70d96422513a91c5342be0e
 F test/tempdb.test 9c869a57e26ef75f9fba19c767097f797bd6ed0c
@@ -729,7 +729,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 4237299935b8bf8c346aacba021113224813bcb9
-R 1225b5a79e6cc1b94c2e3a763a216c4a
+P 93772bd7f56a5158eb46a992ba932f4695cb219f
+R de2290be2f61351bb90dbdb8627e4109
 U drh
-Z 956880f802a30c9fa51b8f0d5897cb04
+Z 51732e5a860d760f0334992770c434bb
index 1b443e483f8b197fb9bfafe2a2646e78b6a7bc0e..78845d8b8b6cb1d5d4016c1f57b4d6627656dac5 100644 (file)
@@ -1 +1 @@
-93772bd7f56a5158eb46a992ba932f4695cb219f
\ No newline at end of file
+33cf83591e6e13875ef6ada5b8ac8ab07619d8bc
\ No newline at end of file
index e7f8e62354077b512c3ba5bf253ee9401165742f..ecf16141dbffe1a9c2ea57a5166377aead0410bd 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.537 2009/05/06 18:42:21 drh Exp $
+** $Id: build.c,v 1.538 2009/05/11 20:53:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -342,6 +342,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
 */
 static void freeIndex(Index *p){
   sqlite3 *db = p->pTable->dbMem;
+  testcase( db==0 );
   sqlite3DbFree(db, p->zColAff);
   sqlite3DbFree(db, p);
 }
@@ -470,6 +471,7 @@ static void sqliteResetColumnNames(Table *pTable){
   int i;
   Column *pCol;
   sqlite3 *db = pTable->dbMem;
+  testcase( db==0 );
   assert( pTable!=0 );
   if( (pCol = pTable->aCol)!=0 ){
     for(i=0; i<pTable->nCol; i++, pCol++){
@@ -500,6 +502,7 @@ void sqlite3DeleteTable(Table *pTable){
 
   if( pTable==0 ) return;
   db = pTable->dbMem;
+  testcase( db==0 );
 
   /* Do not delete the table until the reference count reaches zero. */
   pTable->nRef--;
@@ -654,7 +657,7 @@ int sqlite3TwoPartName(
   int iDb;                    /* Database holding the object */
   sqlite3 *db = pParse->db;
 
-  if( pName2 && pName2->n>0 ){
+  if( ALWAYS(pName2!=0) && pName2->n>0 ){
     if( db->init.busy ) {
       sqlite3ErrorMsg(pParse, "corrupt database");
       pParse->nErr++;
@@ -819,8 +822,8 @@ void sqlite3StartTable(
   pTable->iPKey = -1;
   pTable->pSchema = db->aDb[iDb].pSchema;
   pTable->nRef = 1;
-  pTable->dbMem = db->lookaside.bEnabled ? db : 0;
-  if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable);
+  pTable->dbMem = 0;
+  assert( pParse->pNewTable==0 );
   pParse->pNewTable = pTable;
 
   /* If this is the magic sqlite_sequence table used by autoincrement,
@@ -976,10 +979,9 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
 */
 void sqlite3AddNotNull(Parse *pParse, int onError){
   Table *p;
-  int i;
-  if( (p = pParse->pNewTable)==0 ) return;
-  i = p->nCol-1;
-  if( i>=0 ) p->aCol[i].notNull = (u8)onError;
+  p = pParse->pNewTable;
+  if( p==0 || NEVER(p->nCol<1) ) return;
+  p->aCol[p->nCol-1].notNull = (u8)onError;
 }
 
 /*
@@ -1056,17 +1058,13 @@ char sqlite3AffinityType(const Token *pType){
 */ 
 void sqlite3AddColumnType(Parse *pParse, Token *pType){
   Table *p;
-  int i;
   Column *pCol;
-  sqlite3 *db;
 
-  if( (p = pParse->pNewTable)==0 ) return;
-  i = p->nCol-1;
-  if( i<0 ) return;
-  pCol = &p->aCol[i];
-  db = pParse->db;
-  sqlite3DbFree(db, pCol->zType);
-  pCol->zType = sqlite3NameFromToken(db, pType);
+  p = pParse->pNewTable;
+  if( p==0 || NEVER(p->nCol<1) ) return;
+  pCol = &p->aCol[p->nCol-1];
+  assert( pCol->zType==0 );
+  pCol->zType = sqlite3NameFromToken(pParse->db, pType);
   pCol->affinity = sqlite3AffinityType(pType);
 }
 
@@ -1084,7 +1082,8 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
   Table *p;
   Column *pCol;
   sqlite3 *db = pParse->db;
-  if( (p = pParse->pNewTable)!=0 ){
+  p = pParse->pNewTable;
+  if( p!=0 ){
     pCol = &(p->aCol[p->nCol-1]);
     if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
       sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
@@ -1213,7 +1212,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
   zColl = sqlite3NameFromToken(db, pToken);
   if( !zColl ) return;
 
-  if( sqlite3LocateCollSeq(pParse, zColl, -1) ){
+  if( sqlite3LocateCollSeq(pParse, zColl) ){
     Index *pIdx;
     p->aCol[i].zColl = zColl;
   
@@ -1249,21 +1248,20 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
 ** This routine is a wrapper around sqlite3FindCollSeq().  This routine
 ** invokes the collation factory if the named collation cannot be found
 ** and generates an error message.
+**
+** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
 */
-CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
+CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
   sqlite3 *db = pParse->db;
   u8 enc = ENC(db);
   u8 initbusy = db->init.busy;
   CollSeq *pColl;
 
-  pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
+  pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
   if( !initbusy && (!pColl || !pColl->xCmp) ){
-    pColl = sqlite3GetCollSeq(db, pColl, zName, nName);
+    pColl = sqlite3GetCollSeq(db, pColl, zName);
     if( !pColl ){
-      if( nName<0 ){
-        nName = sqlite3Strlen30(zName);
-      }
-      sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);
+      sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
       pColl = 0;
     }
   }
@@ -1313,61 +1311,6 @@ static int identLength(const char *z){
   return n + 2;
 }
 
-/*
-** 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 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
@@ -1381,7 +1324,7 @@ static int isValidDimension(unsigned char *z){
 ** 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){
+static void identPut(char *z, int *pIdx, char *zSignedIdent){
   unsigned char *zIdent = (unsigned char*)zSignedIdent;
   int i, j, needQuote;
   i = *pIdx;
@@ -1391,21 +1334,7 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent, int isTypename){
   }
   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];
-    }
+    needQuote = zIdent[j];
   }
 
   if( needQuote ) z[i++] = '"';
@@ -1426,18 +1355,14 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent, int isTypename){
 static char *createTableStmt(sqlite3 *db, Table *p){
   int i, k, n;
   char *zStmt;
-  char *zSep, *zSep2, *zEnd, *z;
+  char *zSep, *zSep2, *zEnd;
   Column *pCol;
   n = 0;
   for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
-    n += identLength(pCol->zName);
-    z = pCol->zType;
-    if( z ){
-      n += identLength(z);
-    }
+    n += identLength(pCol->zName) + 5;
   }
   n += identLength(p->zName);
-  if( n<50 ){
+  if( n<50 ){ 
     zSep = "";
     zSep2 = ",";
     zEnd = ")";
@@ -1454,18 +1379,44 @@ static char *createTableStmt(sqlite3 *db, Table *p){
   }
   sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
   k = sqlite3Strlen30(zStmt);
-  identPut(zStmt, &k, p->zName, 0);
+  identPut(zStmt, &k, p->zName);
   zStmt[k++] = '(';
   for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
+    static const char * const azType[] = {
+        /* SQLITE_AFF_TEXT    */ " TEXT",
+        /* SQLITE_AFF_NONE    */ "",
+        /* SQLITE_AFF_NUMERIC */ " NUM",
+        /* SQLITE_AFF_INTEGER */ " INT",
+        /* SQLITE_AFF_REAL    */ " REAL"
+    };
+    int len;
+    const char *zType;
+
     sqlite3_snprintf(n-k, &zStmt[k], zSep);
     k += sqlite3Strlen30(&zStmt[k]);
     zSep = zSep2;
-    identPut(zStmt, &k, pCol->zName, 0);
-    if( (z = pCol->zType)!=0 ){
-      zStmt[k++] = ' ';
-      assert( (int)(sqlite3Strlen30(z)+k+1)<=n );
-      identPut(zStmt, &k, z, 1);
+    identPut(zStmt, &k, pCol->zName);
+    assert( pCol->affinity-SQLITE_AFF_TEXT >= 0 );
+    assert( pCol->affinity-SQLITE_AFF_TEXT < sizeof(azType)/sizeof(azType[0]) );
+    testcase( pCol->affinity==SQLITE_AFF_TEXT );
+    testcase( pCol->affinity==SQLITE_AFF_NONE );
+    testcase( pCol->affinity==SQLITE_AFF_NUMERIC );
+    testcase( pCol->affinity==SQLITE_AFF_INTEGER );
+    testcase( pCol->affinity==SQLITE_AFF_REAL );
+    
+    zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
+    len = sqlite3Strlen30(zType);
+#ifndef NDEBUG
+    if( pCol->affinity!=SQLITE_AFF_NONE ){
+       Token typeToken;
+       typeToken.z = (u8*)zType;
+       typeToken.n = len;
+       assert( pCol->affinity==sqlite3AffinityType(&typeToken) );
     }
+#endif
+    memcpy(&zStmt[k], zType, len);
+    k += len;
+    assert( k<=n );
   }
   sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
   return zStmt;
@@ -2647,7 +2598,7 @@ void sqlite3CreateIndex(
         zColl = db->pDfltColl->zName;
       }
     }
-    if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){
+    if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
       goto exit_create_index;
     }
     pIndex->azColl[i] = zColl;
@@ -3584,7 +3535,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
     assert( pName1->z );
     zColl = sqlite3NameFromToken(pParse->db, pName1);
     if( !zColl ) return;
-    pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
+    pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
     if( pColl ){
       if( zColl ){
         reindexDatabases(pParse, zColl);
@@ -3640,7 +3591,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
     for(i=0; i<nCol; i++){
       char *zColl = pIdx->azColl[i];
       assert( zColl );
-      pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1);
+      pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
       pKey->aSortOrder[i] = pIdx->aSortOrder[i];
     }
     pKey->nField = (u16)nCol;
index 2c81c95229e751548f6874e21547477fb59e2d68..3f75760ac46a7b06c32d16a229da30370742e962 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains functions used to access the internal hash tables
 ** of user defined functions and collation sequences.
 **
-** $Id: callback.c,v 1.39 2009/05/03 20:23:53 drh Exp $
+** $Id: callback.c,v 1.40 2009/05/11 20:53:29 drh Exp $
 */
 
 #include "sqliteInt.h"
 ** in the database text encoding of name zName, length nName.
 ** If the collation sequence
 */
-static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
+static void callCollNeeded(sqlite3 *db, const char *zName){
   assert( !db->xCollNeeded || !db->xCollNeeded16 );
-  if( nName<0 ) nName = sqlite3Strlen30(zName);
   if( db->xCollNeeded ){
-    char *zExternal = sqlite3DbStrNDup(db, zName, nName);
+    char *zExternal = sqlite3DbStrDup(db, zName);
     if( !zExternal ) return;
     db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
     sqlite3DbFree(db, zExternal);
@@ -36,7 +35,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
   if( db->xCollNeeded16 ){
     char const *zExternal;
     sqlite3_value *pTmp = sqlite3ValueNew(db);
-    sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
+    sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC);
     zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
     if( zExternal ){
       db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
@@ -56,11 +55,10 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
 static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
   CollSeq *pColl2;
   char *z = pColl->zName;
-  int n = sqlite3Strlen30(z);
   int i;
   static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
   for(i=0; i<3; i++){
-    pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
+    pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0);
     if( pColl2->xCmp!=0 ){
       memcpy(pColl, pColl2, sizeof(CollSeq));
       pColl->xDel = 0;         /* Do not copy the destructor */
@@ -82,25 +80,26 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
 ** The return value is either the collation sequence to be used in database
 ** db for collation type name zName, length nName, or NULL, if no collation
 ** sequence can be found.
+**
+** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
 */
 CollSeq *sqlite3GetCollSeq(
-  sqlite3* db, 
-  CollSeq *pColl, 
-  const char *zName, 
-  int nName
+  sqlite3* db,          /* The database connection */
+  CollSeq *pColl,       /* Collating sequence with native encoding, or NULL */
+  const char *zName     /* Collating sequence name */
 ){
   CollSeq *p;
 
   p = pColl;
   if( !p ){
-    p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
+    p = sqlite3FindCollSeq(db, ENC(db), zName, 0);
   }
   if( !p || !p->xCmp ){
     /* No collation sequence of this type for this encoding is registered.
     ** Call the collation factory to see if it can supply us with one.
     */
-    callCollNeeded(db, zName, nName);
-    p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
+    callCollNeeded(db, zName);
+    p = sqlite3FindCollSeq(db, ENC(db), zName, 0);
   }
   if( p && !p->xCmp && synthCollSeq(db, p) ){
     p = 0;
@@ -123,7 +122,7 @@ CollSeq *sqlite3GetCollSeq(
 int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
   if( pColl ){
     const char *zName = pColl->zName;
-    CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1);
+    CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName);
     if( !p ){
       if( pParse->nErr==0 ){
         sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
@@ -152,13 +151,12 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
 ** each collation sequence structure.
 */
 static CollSeq *findCollSeqEntry(
-  sqlite3 *db,
-  const char *zName,
-  int nName,
-  int create
+  sqlite3 *db,          /* Database connection */
+  const char *zName,    /* Name of the collating sequence */
+  int create            /* Create a new entry if true */
 ){
   CollSeq *pColl;
-  if( nName<0 ) nName = sqlite3Strlen30(zName);
+  int nName = sqlite3Strlen30(zName);
   pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
 
   if( 0==pColl && create ){
@@ -202,17 +200,18 @@ static CollSeq *findCollSeqEntry(
 ** this routine.  sqlite3LocateCollSeq() invokes the collation factory
 ** if necessary and generates an error message if the collating sequence
 ** cannot be found.
+**
+** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
 */
 CollSeq *sqlite3FindCollSeq(
   sqlite3 *db,
   u8 enc,
   const char *zName,
-  int nName,
   int create
 ){
   CollSeq *pColl;
   if( zName ){
-    pColl = findCollSeqEntry(db, zName, nName, create);
+    pColl = findCollSeqEntry(db, zName, create);
   }else{
     pColl = db->pDfltColl;
   }
index 9ec98b04b60c3fa19bb8eb75e4249b8b5f30414f..b6aba99217f13a9a4073f9fb4bcd3a9bee39be24 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.433 2009/05/09 00:18:38 drh Exp $
+** $Id: expr.c,v 1.434 2009/05/11 20:53:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -69,7 +69,7 @@ Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
   sqlite3 *db = pParse->db;
   zColl = sqlite3NameFromToken(db, pCollName);
   if( pExpr && zColl ){
-    pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
+    pColl = sqlite3LocateCollSeq(pParse, zColl);
     if( pColl ){
       pExpr->pColl = pColl;
       pExpr->flags |= EP_ExpCollate;
@@ -99,7 +99,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
       if( j>=0 ){
         sqlite3 *db = pParse->db;
         zColl = p->pTab->aCol[j].zColl;
-        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
+        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
         pExpr->pColl = pColl;
       }
       break;
@@ -1377,7 +1377,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
 
       for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
         if( (pIdx->aiColumn[0]==iCol)
-         && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0))
+         && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0))
          && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
         ){
           int iMem = ++pParse->nMem;
index 7122e194f5c2ef7def4236aa94b8438f6c19ec62..b1f7e2f499a3f52017d0c555301387aa691011bf 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.550 2009/05/09 18:59:42 drh Exp $
+** $Id: main.c,v 1.551 2009/05/11 20:53:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1361,7 +1361,7 @@ static int createCollation(
 ){
   CollSeq *pColl;
   int enc2;
-  int nName;
+  int nName = sqlite3Strlen30(zName);
   
   assert( sqlite3_mutex_held(db->mutex) );
 
@@ -1383,8 +1383,7 @@ static int createCollation(
   ** sequence. If so, and there are active VMs, return busy. If there
   ** are no active VMs, invalidate any pre-compiled statements.
   */
-  nName = sqlite3Strlen30(zName);
-  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 0);
+  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
   if( pColl && pColl->xCmp ){
     if( db->activeVdbeCnt ){
       sqlite3Error(db, SQLITE_BUSY, 
@@ -1414,7 +1413,7 @@ static int createCollation(
     }
   }
 
-  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, nName, 1);
+  pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 1);
   if( pColl ){
     pColl->xCmp = xCompare;
     pColl->pUser = pCtx;
@@ -1603,7 +1602,7 @@ static int openDatabase(
   if( db->mallocFailed ){
     goto opendb_out;
   }
-  db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
+  db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
   assert( db->pDfltColl!=0 );
 
   /* Also add a UTF-8 case-insensitive collation sequence. */
@@ -1611,7 +1610,7 @@ static int openDatabase(
 
   /* Set flags on the built-in collating sequences */
   db->pDfltColl->type = SQLITE_COLL_BINARY;
-  pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0);
+  pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 0);
   if( pColl ){
     pColl->type = SQLITE_COLL_NOCASE;
   }
index c5f4de90429a97f4181f2256359c65b80a838579..909a74acef2ccd0b4f27a78d72335017c7bb399b 100644 (file)
@@ -13,7 +13,7 @@
 ** interface, and routines that contribute to loading the database schema
 ** from disk.
 **
-** $Id: prepare.c,v 1.117 2009/04/20 17:43:03 drh Exp $
+** $Id: prepare.c,v 1.118 2009/05/11 20:53:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -258,7 +258,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
     if( iDb==0 ){
       /* If opening the main database, set ENC(db). */
       ENC(db) = (u8)meta[4];
-      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
+      db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0);
     }else{
       /* If opening an attached database, the encoding much match ENC(db) */
       if( meta[4]!=ENC(db) ){
index d1c0fb44edb6e282795800666f5fadc1acab0729..af1c66bd48b3967692755da75e5f3e302270d803 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.512 2009/05/03 20:23:54 drh Exp $
+** $Id: select.c,v 1.513 2009/05/11 20:53:29 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1223,6 +1223,7 @@ static void selectAddColumnTypeAndCollation(
     p = a[i].pExpr;
     pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
     pCol->affinity = sqlite3ExprAffinity(p);
+    if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
     pColl = sqlite3ExprCollSeq(pParse, p);
     if( pColl ){
       pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
index b5d786d73fdbe6f19a604b721b17384d604d9953..fccccb656f3b714f67ad16eeb225efe33238a255 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.869 2009/05/07 14:11:52 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.870 2009/05/11 20:53:29 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -2641,8 +2641,8 @@ void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
 int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
 const char *sqlite3ErrStr(int);
 int sqlite3ReadSchema(Parse *pParse);
-CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int);
-CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
+CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
+CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
 CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
 Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
@@ -2680,7 +2680,7 @@ int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
 void sqlite3ColumnDefault(Vdbe *, Table *, int);
 void sqlite3AlterFinishAddColumn(Parse *, Token *);
 void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
+CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char*);
 char sqlite3AffinityType(const Token*);
 void sqlite3Analyze(Parse*, Token*, Token*);
 int sqlite3InvokeBusyHandler(BusyHandler*);
index 9d12296aaa2a35e6ad2282c30cdfabdd7b6d6ec3..c4570088799bdd54ba03ddc170cbcb39ca6e21cd 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the CREATE TABLE statement.
 #
-# $Id: table.test,v 1.51 2009/04/28 15:43:45 drh Exp $
+# $Id: table.test,v 1.52 2009/05/11 20:53:29 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -337,13 +337,13 @@ do_test table-8.1.1 {
     SELECT sql FROM sqlite_master WHERE name='t2';
   }
 } {{CREATE TABLE t2(
-  "desc" text,
-  "asc" text,
-  "key" int,
-  "14_vac" boolean,
-  fuzzy_dog_12 varchar(10),
-  "begin" blob,
-  "end" clob
+  "desc" TEXT,
+  "asc" TEXT,
+  "key" INT,
+  "14_vac" NUM,
+  fuzzy_dog_12 TEXT,
+  "begin",
+  "end" TEXT
 )}}
 do_test table-8.2 {
   execsql {
@@ -406,7 +406,7 @@ do_test table-8.9 {
     CREATE TABLE t11 AS SELECT * FROM t10;
     SELECT sql FROM sqlite_master WHERE name = 't11';
   }
-} {{CREATE TABLE t11("col.1" "char.3")}}
+} {{CREATE TABLE t11("col.1" TEXT)}}
 do_test table-8.10 {
   execsql {
     CREATE TABLE t12(
@@ -422,13 +422,13 @@ do_test table-8.10 {
     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"
+  a INT,
+  b TEXT,
+  c TEXT,
+  d TEXT,
+  e TEXT,
+  f TEXT,
+  g INT
 )}}
 
 # Make sure we cannot have duplicate column names within a table.
@@ -585,7 +585,7 @@ do_test table-12.2 {
   execsql {
     SELECT sql FROM sqlite_master WHERE tbl_name = 't8'
   }
-} {{CREATE TABLE t8(b number(5,10),h,i integer,j BLOB)}}
+} {{CREATE TABLE t8(b NUM,h,i INT,j)}}
 
 #--------------------------------------------------------------------
 # Test cases table-13.*