]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Store the collating sequence name for each column of a table as an
authordrh <>
Thu, 5 Aug 2021 15:27:19 +0000 (15:27 +0000)
committerdrh <>
Thu, 5 Aug 2021 15:27:19 +0000 (15:27 +0000)
extension to the column name, for an additional savings in the heap space
needed to hold the schema.

FossilOrigin-Name: 832ac4c1ee384be0de72a4bdd55ed87e0f8294e7df5eefcf6b4942db3d85a69e

manifest
manifest.uuid
src/alter.c
src/build.c
src/expr.c
src/fkey.c
src/insert.c
src/main.c
src/select.c
src/sqliteInt.h
src/wherecode.c

index 019a53ba43dbfea969dfbfeee2336819c0aa753f..0f3d8820afc3e3ca11aded0a2ee34290c4074cab 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sNEVER()\smacros\son\srecently\sintroduced\sunreachable\sbranches.
-D 2021-08-04T14:50:23.224
+C Store\sthe\scollating\ssequence\sname\sfor\seach\scolumn\sof\sa\stable\sas\san\nextension\sto\sthe\scolumn\sname,\sfor\san\sadditional\ssavings\sin\sthe\sheap\sspace\nneeded\sto\shold\sthe\sschema.
+D 2021-08-05T15:27:19.168
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -478,7 +478,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
 F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c f2a1c9eeed22a40ac88285fb393aff1a21d153d80bde1955202191430beb9e09
+F src/alter.c 38975b971a4c36dbcc8004c74b492213a851ab368d29238c531a22636508a5d4
 F src/analyze.c abbaaf7dca79d1c31c713500324fc0b55bf3eeac5b7b07001452a3d0f210de4f
 F src/attach.c a514e81758ba7b3a3a0501faf70af6cfc509de8810235db726cfc9f25165e929
 F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
@@ -488,7 +488,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c e204a9c8fb4fe5dbb910a863ba487f4af9b5c501254ec4ccbfcdd6b1f65b7fb4
 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
 F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
-F src/build.c 9d607ffcaeb6120daf8fdc229b064f9de1be3cfc7188d0d4fff010ca2f05c835
+F src/build.c ac4c6990ff076676bf172442c7098d2ae8370adf8c3ac6280aef23d05336ec9c
 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1
@@ -496,19 +496,19 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
 F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
 F src/delete.c 3ce6af6b64c8b476de51ccc32da0cb3142d42e65754e1d8118addf65b8bcba15
-F src/expr.c 0d541b9f9ecddf9d6d310f31922006f03509d7264ef53ac39c391b82a62383f9
+F src/expr.c e98375fc63552cc8cdd36a41bdca3039cb603d9fe67abd9c9f40adae8405fbc5
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 9e2b4127463c18e6351ff3665475045f048dd2e2f72a3761721e4ff6c6a45abf
+F src/fkey.c 1905af1821b88321e1bb9d6a69e704495b6844a9b6c29398d40117cc251e893c
 F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c
 F src/global.c 5eba017ebbd887e2365e6e6e815e1619e41406b8946d17594e94116174787df5
 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c c6419bc4b447f3d4cdb7b1167690baaea3b796a80cea48e7cf26da65487d430d
+F src/insert.c 4ebff642574d3866316439b3dfce165f80e130e8969853c656d71b2afc5dd73c
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e
-F src/main.c 2c17a667133d2d1666319cfef975a48aa640a3de0c57d68b362372a12ad5557b
+F src/main.c 5c8c47584612a60bd05c309aadbbfa4728824df0a94148d2a4e7e97d34676a22
 F src/malloc.c cbc93cdd429c4594912017d92ab656e2579aca64dbd1c6888551275bed46f25b
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -544,12 +544,12 @@ F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
 F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 52041124629704feb24b1bc7dabf8ec03a0857c69d23f2dd0c33c9ed3d074adb
+F src/select.c 63077c0243ded1432d97c90c1a4c3419b3a574b36634c674599a68bfe4c3bdc2
 F src/shell.c.in 24b99dae8818d1a234732d73f4d5b49f12b510bc62735a41c04e314fafae09e3
 F src/sqlite.h.in 43fcf0fe2af04081f420a906fc020bde1243851ba44b0aa567a27f94bf8c3145
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
-F src/sqliteInt.h 6f02ceb8d6b8784faf7218bd58b59580837c9e95e54a5b34d48ae93504ba67ce
+F src/sqliteInt.h 3dbca904012fc663b4e8c51ad644eb99ba17bb03589de0b1358496fa73dc8039
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -633,7 +633,7 @@ F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac
 F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5
 F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b
-F src/wherecode.c ef36790a797fa679f58dbd51930e3ee7ef7cb6c906ae412032e4d319a36a2eef
+F src/wherecode.c 9b33f463a279feeee69622b747b0050f0b836eb8b5ac48599ba3a6bfbea798a7
 F src/whereexpr.c 3a9144a9d52e110efdc012a73b1574e7b2b4df4bf98949387cb620295eba0975
 F src/window.c 420167512050a0dfc0f0115b9f0c7d299da9759c9bb2ae83a61fb8d730a5707f
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1920,7 +1920,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 164662ef01ad45ca570c44631a1117cccce6e34b00dbba7f422c089e8ffaa932
-R 4753b5d71292c9ebc3a2ba2d009a17d6
+P 806939eb5947f9187dc9c4814b26e9f94ec0186596c7be97981dbea7c2169c26
+R c05bd2cc9216ebbd1f44d1211c54be18
 U drh
-Z 98a283af33e1b680aea1e6779f6dcf99
+Z 761dcef26d3489b5940c28f76fcc5ec9
index de16e7531737908b681d5aa507592da6dd1ad707..cd11bd283ebac6c1d24d77dc02390a786ae67376 100644 (file)
@@ -1 +1 @@
-806939eb5947f9187dc9c4814b26e9f94ec0186596c7be97981dbea7c2169c26
\ No newline at end of file
+832ac4c1ee384be0de72a4bdd55ed87e0f8294e7df5eefcf6b4942db3d85a69e
\ No newline at end of file
index 5780d2df0cc4a47a4690d677c970d6fa376892eb..c059a62ecd05855ad8acefb3c91684ff4f0479a8 100644 (file)
@@ -532,7 +532,6 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
     Column *pCol = &pNew->aCol[i];
     pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
     pCol->hName = sqlite3StrIHash(pCol->zCnName);
-    pCol->zCnColl = 0;
   }
   assert( !IsVirtual(pNew) );
   pNew->u.tab.pDfltList = sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
index 942dc85f8b80c1ae316900a68fde182fd8522bb9..6343da4f589d476cdc4ccb64d3da390b780a86ff 100644 (file)
@@ -710,6 +710,45 @@ Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
   return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
 }
 
+/*
+** Set the collating sequence name for a column.
+*/
+void sqlite3ColumnSetColl(
+  sqlite3 *db,
+  Column *pCol,
+  const char *zColl
+){
+  int nColl;
+  int n;
+  char *zNew;
+  assert( zColl!=0 );
+  n = sqlite3Strlen30(pCol->zCnName) + 1;
+  if( pCol->colFlags & COLFLAG_HASTYPE ){
+    n += sqlite3Strlen30(pCol->zCnName+n) + 1;
+  }
+  nColl = sqlite3Strlen30(zColl) + 1;
+  zNew = sqlite3DbRealloc(db, pCol->zCnName, nColl+n);
+  if( zNew ){
+    pCol->zCnName = zNew;
+    memcpy(pCol->zCnName + n, zColl, nColl);
+    pCol->colFlags |= COLFLAG_HASCOLL;
+  }
+}
+
+/*
+** Return the collating squence name for a column
+*/
+const char *sqlite3ColumnColl(Column *pCol){
+  const char *z;
+  if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0;
+  z = pCol->zCnName;
+  while( *z ){ z++; }
+  if( pCol->colFlags & COLFLAG_HASTYPE ){
+    do{ z++; }while( *z );
+  }
+  return z+1;
+}
+
 /*
 ** Delete memory allocated for the column names of a table or view (the
 ** Table.aCol[] array).
@@ -722,7 +761,6 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
     for(i=0; i<pTable->nCol; i++, pCol++){
       assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
       sqlite3DbFree(db, pCol->zCnName);
-      sqlite3DbFree(db, pCol->zCnColl);
     }
     sqlite3DbFree(db, pTable->aCol);
     if( !IsVirtual(pTable) ){
@@ -1891,8 +1929,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
 
   if( sqlite3LocateCollSeq(pParse, zColl) ){
     Index *pIdx;
-    sqlite3DbFree(db, p->aCol[i].zCnColl);
-    p->aCol[i].zCnColl = zColl;
+    sqlite3ColumnSetColl(db, &p->aCol[i], zColl);
   
     /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
     ** then an index may have been created on this column before the
@@ -1901,12 +1938,11 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
     for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
       assert( pIdx->nKeyCol==1 );
       if( pIdx->aiColumn[0]==i ){
-        pIdx->azColl[0] = p->aCol[i].zCnColl;
+        pIdx->azColl[0] = sqlite3ColumnColl(&p->aCol[i]);
       }
     }
-  }else{
-    sqlite3DbFree(db, zColl);
   }
+  sqlite3DbFree(db, zColl);
 }
 
 /* Change the most recently parsed column to be a GENERATED ALWAYS AS
@@ -4066,7 +4102,7 @@ void sqlite3CreateIndex(
       zExtra += nColl;
       nExtra -= nColl;
     }else if( j>=0 ){
-      zColl = pTab->aCol[j].zCnColl;
+      zColl = sqlite3ColumnColl(&pTab->aCol[j]);
     }
     if( !zColl ) zColl = sqlite3StrBINARY;
     if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
index 0f900c0c6cc534a79a8818f5749ea7ef8b8439f5..34f14e36878cef31841e4004648a3af98fbf3fab 100644 (file)
@@ -173,7 +173,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
       ** a TK_COLUMN but was previously evaluated and cached in a register */
       int j = p->iColumn;
       if( j>=0 ){
-        const char *zColl = p->y.pTab->aCol[j].zCnColl;
+        const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
         pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
       }
       break;
index 5105b5cc793ee58280e83e83b9ae591d9bf8c82d..5888e558fba24df4287fd3c6389b9d50adf701ea 100644 (file)
@@ -259,7 +259,7 @@ int sqlite3FkLocateIndex(
           /* If the index uses a collation sequence that is different from
           ** the default collation sequence for the column, this index is
           ** unusable. Bail out early in this case.  */
-          zDfltColl = pParent->aCol[iCol].zCnColl;
+          zDfltColl = sqlite3ColumnColl(&pParent->aCol[iCol]);
           if( !zDfltColl ) zDfltColl = sqlite3StrBINARY;
           if( sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
 
@@ -487,7 +487,7 @@ static Expr *exprTableRegister(
       pCol = &pTab->aCol[iCol];
       pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
       pExpr->affExpr = pCol->affinity;
-      zColl = pCol->zCnColl;
+      zColl = sqlite3ColumnColl(pCol);
       if( zColl==0 ) zColl = db->pDfltColl->zName;
       pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
     }else{
index 06952586b0eced2ba19f8cdf4e74421d690d6f35..0692198b1ee5db54dac62d2d7311184e9a000dc5 100644 (file)
@@ -2843,7 +2843,8 @@ static int xferOptimization(
     if( pDestCol->affinity!=pSrcCol->affinity ){
       return 0;    /* Affinity must be the same on all columns */
     }
-    if( sqlite3_stricmp(pDestCol->zCnColl, pSrcCol->zCnColl)!=0 ){
+    if( sqlite3_stricmp(sqlite3ColumnColl(pDestCol), 
+                        sqlite3ColumnColl(pSrcCol))!=0 ){
       return 0;    /* Collating sequence must be the same on all columns */
     }
     if( pDestCol->notNull && !pSrcCol->notNull ){
index 3c1191c3683876ec1f424d902ddc8ce047aed15b..a37301a6409b78e0ca65f91e6a1000678db5f09a 100644 (file)
@@ -3769,7 +3769,7 @@ int sqlite3_table_column_metadata(
   */ 
   if( pCol ){
     zDataType = sqlite3ColumnType(pCol,0);
-    zCollSeq = pCol->zCnColl;
+    zCollSeq = sqlite3ColumnColl(pCol);
     notnull = pCol->notNull!=0;
     primarykey  = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
     autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
index 064ea758d8a5d7f4c9ac4869c09285bdfcaa9258..375050bdcd64755f98d4e8d329d837fb85359503 100644 (file)
@@ -2193,8 +2193,9 @@ void sqlite3SelectAddColumnTypeAndCollation(
     }
     if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
     pColl = sqlite3ExprCollSeq(pParse, p);
-    if( pColl && pCol->zCnColl==0 ){
-      pCol->zCnColl = sqlite3DbStrDup(db, pColl->zName);
+    if( pColl && (pCol->colFlags & COLFLAG_HASCOLL)==0 ){
+      assert( pTab->pIndex==0 );
+      sqlite3ColumnSetColl(db, pCol, pColl->zName);
     }
   }
   pTab->szTabRow = 1; /* Any non-zero value works */
index 083ba5a3359de6e5c20d6c6d9f82860437aeac79..9f4d211752a251602070988237e96072236e1e15 100644 (file)
@@ -2028,10 +2028,17 @@ struct Module {
 **                            or equal to the table column index.  It is
 **                            equal if and only if there are no VIRTUAL
 **                            columns to the left.
+**
+** Notes on zCnName:
+** The zCnName field stores the name of the column, the datatype of the
+** column, and the collating sequence for the column, in that order, all in
+** a single allocation.  Each string is 0x00 terminated.  The datatype
+** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
+** collating sequence name is only included if the COLFLAG_HASCOLL bit is
+** set.
 */
 struct Column {
   char *zCnName;   /* Name of this column */
-  char *zCnColl;   /* Collating sequence.  If NULL, use the default */
   u8 notNull : 4;  /* An OE_ code for handling a NOT NULL constraint */
   u8 eType : 4;    /* One of the standard types */
   char affinity;   /* One of the SQLITE_AFF_... values */
@@ -2072,6 +2079,7 @@ struct Column {
 #define COLFLAG_STORED    0x0040   /* GENERATED ALWAYS AS ... STORED */
 #define COLFLAG_NOTAVAIL  0x0080   /* STORED column not yet calculated */
 #define COLFLAG_BUSY      0x0100   /* Blocks recursion on GENERATED columns */
+#define COLFLAG_HASCOLL   0x0200   /* Has collating sequence name in zCnName */
 #define COLFLAG_GENERATED 0x0060   /* Combo: _STORED, _VIRTUAL */
 #define COLFLAG_NOINSERT  0x0062   /* Combo: _HIDDEN, _STORED, _VIRTUAL */
 
@@ -4398,6 +4406,8 @@ void sqlite3CollapseDatabaseArray(sqlite3*);
 void sqlite3CommitInternalChanges(sqlite3*);
 void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
 Expr *sqlite3ColumnExpr(Table*,Column*);
+void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
+const char *sqlite3ColumnColl(Column*);
 void sqlite3DeleteColumnNames(sqlite3*,Table*);
 void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
 int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
index f3589bb0ac75c4b7098b9dcfc24d9af8368807f7..28b417c9aefa21cbfe5270ac34f0e813288a13bb 100644 (file)
@@ -1241,8 +1241,9 @@ static void whereIndexExprTrans(
 #ifndef SQLITE_OMIT_GENERATED_COLUMNS
     }else if( iRef>=0
        && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
-       && (pTab->aCol[iRef].zCnColl==0
-           || sqlite3StrICmp(pTab->aCol[iRef].zCnColl, sqlite3StrBINARY)==0)
+       && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
+           || sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]),
+                                               sqlite3StrBINARY)==0)
     ){
       /* Check to see if there are direct references to generated columns
       ** that are contained in the index.  Pulling the generated column