aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2021-08-05 15:27:19 +0000
committerdrh <>2021-08-05 15:27:19 +0000
commit65b400931ddbaaa2059094a014ecf46c0840857c (patch)
tree26c831dfb7bd1bfb567aad2bd7afd20b91b2268a /src
parent324f91a591ba4578917ab0436a966ff33b163a2a (diff)
downloadsqlite-65b400931ddbaaa2059094a014ecf46c0840857c.tar.gz
sqlite-65b400931ddbaaa2059094a014ecf46c0840857c.zip
Store the collating sequence name for each column of a table as an
extension to the column name, for an additional savings in the heap space needed to hold the schema. FossilOrigin-Name: 832ac4c1ee384be0de72a4bdd55ed87e0f8294e7df5eefcf6b4942db3d85a69e
Diffstat (limited to 'src')
-rw-r--r--src/alter.c1
-rw-r--r--src/build.c50
-rw-r--r--src/expr.c2
-rw-r--r--src/fkey.c4
-rw-r--r--src/insert.c3
-rw-r--r--src/main.c2
-rw-r--r--src/select.c5
-rw-r--r--src/sqliteInt.h12
-rw-r--r--src/wherecode.c5
9 files changed, 66 insertions, 18 deletions
diff --git a/src/alter.c b/src/alter.c
index 5780d2df0..c059a62ec 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -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);
diff --git a/src/build.c b/src/build.c
index 942dc85f8..6343da4f5 100644
--- a/src/build.c
+++ b/src/build.c
@@ -711,6 +711,45 @@ Expr *sqlite3ColumnExpr(Table *pTab, Column *pCol){
}
/*
+** 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) ){
diff --git a/src/expr.c b/src/expr.c
index 0f900c0c6..34f14e368 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -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;
diff --git a/src/fkey.c b/src/fkey.c
index 5105b5cc7..5888e558f 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -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{
diff --git a/src/insert.c b/src/insert.c
index 06952586b..0692198b1 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -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 ){
diff --git a/src/main.c b/src/main.c
index 3c1191c36..a37301a64 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
diff --git a/src/select.c b/src/select.c
index 064ea758d..375050bdc 100644
--- a/src/select.c
+++ b/src/select.c
@@ -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 */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 083ba5a33..9f4d21175 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -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**);
diff --git a/src/wherecode.c b/src/wherecode.c
index f3589bb0a..28b417c9a 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -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