[tarantool-patches] [PATCH v1 4/4] sql: get rid of Column structure
Kirill Shcherbatov
kshcherbatov at tarantool.org
Mon Jul 16 15:28:01 MSK 2018
Get rid of is_primkey in Column structure as it become
redundant. Moved the last member coll with collation pointer
to field_def structure. Finally, dropped Column.
---
src/box/field_def.c | 1 +
src/box/field_def.h | 2 ++
src/box/sql/alter.c | 16 +++-------
src/box/sql/build.c | 79 +++++++++++++++++--------------------------------
src/box/sql/resolve.c | 11 +++----
src/box/sql/select.c | 43 ++++++++++-----------------
src/box/sql/sqliteInt.h | 23 +++++++-------
7 files changed, 65 insertions(+), 110 deletions(-)
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 8dbead6..12cc3b2 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -106,6 +106,7 @@ const struct field_def field_def_default = {
.is_nullable = false,
.nullable_action = ON_CONFLICT_ACTION_DEFAULT,
.coll_id = COLL_NONE,
+ .coll = NULL,
.default_value = NULL,
.default_value_expr = NULL
};
diff --git a/src/box/field_def.h b/src/box/field_def.h
index 05f80d4..c8f158c 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -123,6 +123,8 @@ struct field_def {
enum on_conflict_action nullable_action;
/** Collation ID for string comparison. */
uint32_t coll_id;
+ /** Collating sequence for string comparison. */
+ struct coll *coll;
/** 0-terminated SQL expression for DEFAULT value. */
char *default_value;
/** AST for parsed default value. */
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index fe54e55..4f50988 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -146,7 +146,6 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
Table *pNew; /* Copy of pParse->pNewTable */
Table *pTab; /* Table being altered */
const char *zTab; /* Table name */
- Column *pCol; /* The new column */
Expr *pDflt; /* Default value for the new column */
sqlite3 *db; /* The database connection; */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
@@ -161,7 +160,6 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
/* Skip the "sqlite_altertab_" prefix on the name. */
zTab = &pNew->def->name[16];
- pCol = &pNew->aCol[pNew->def->field_count - 1];
assert(pNew->def != NULL);
pDflt = space_column_default_expr(SQLITE_PAGENO_TO_SPACEID(pNew->tnum),
pNew->def->field_count - 1);
@@ -181,7 +179,9 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
* If there is a NOT NULL constraint, then the default value for the
* column must not be NULL.
*/
- if (pCol->is_primkey) {
+ struct Index *pk = sqlite3PrimaryKeyIndex(pTab);
+ if (index_has_column(pk->aiColumn, pk->nColumn,
+ pNew->def->field_count - 1)) {
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
return;
}
@@ -299,19 +299,11 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
nAlloc = (((pNew->def->field_count - 1) / 8) * 8) + 8;
assert((uint32_t)nAlloc >= pNew->def->field_count && nAlloc % 8 == 0 &&
nAlloc - pNew->def->field_count < 8);
- pNew->aCol =
- (Column *) sqlite3DbMallocZero(db, sizeof(Column) * nAlloc);
/* FIXME: pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); */
/* FIXME: if (!pNew->aCol || !pNew->zName) { */
- if (!pNew->aCol) {
- assert(db->mallocFailed);
- goto exit_begin_add_column;
- }
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->def->field_count);
for (i = 0; i < pNew->def->field_count; i++) {
- Column *pCol = &pNew->aCol[i];
/* FIXME: pNew->def->name = sqlite3DbStrDup(db, pCol->zName); */
- pCol->coll = NULL;
+ pNew->def->fields[i].coll = NULL;
pNew->def->fields[i].coll_id = COLL_NONE;
}
pNew->pSchema = db->pSchema;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index ec0bc4b..a6f3559 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -114,6 +114,16 @@ sql_finish_coding(struct Parse *parse_context)
}
}
+bool
+index_has_column(const i16 *parts, int parts_count, int column_idx)
+{
+ while (parts_count-- > 0) {
+ if (column_idx == *(parts++))
+ return 1;
+ }
+ return 0;
+}
+
/**
* This is a function which should be called during execution
* of sqlite3EndTable. It ensures that only PRIMARY KEY
@@ -131,10 +141,10 @@ check_on_conflict_replace_entries(struct Table *table)
for (int i = 0; i < (int)table->def->field_count; i++) {
enum on_conflict_action on_error =
table->def->fields[i].nullable_action;
+ struct Index *pk = sqlite3PrimaryKeyIndex(table);
if (on_error == ON_CONFLICT_ACTION_REPLACE &&
- table->aCol[i].is_primkey == false) {
+ !index_has_column(pk->aiColumn, pk->nColumn, i))
return true;
- }
}
/* Check all UNIQUE constraints. */
for (struct Index *idx = table->pIndex; idx; idx = idx->pNext) {
@@ -337,7 +347,6 @@ deleteTable(sqlite3 * db, Table * pTable)
/* Delete the Table structure itself.
*/
sqlite3HashClear(&pTable->idxHash);
- sqlite3DbFree(db, pTable->aCol);
sqlite3DbFree(db, pTable->zColAff);
assert(pTable->def != NULL);
/* Do not delete pTable->def allocated on region. */
@@ -601,7 +610,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
int i;
char *z;
char *zType;
- Column *pCol;
sqlite3 *db = pParse->db;
if ((p = pParse->pNewTable) == 0)
return;
@@ -639,17 +647,6 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
return;
}
}
- if ((p->def->field_count & 0x7) == 0) {
- Column *aNew =
- sqlite3DbRealloc(db, p->aCol,
- (p->def->field_count + 8) *
- sizeof(p->aCol[0]));
- if (aNew == NULL)
- return;
- p->aCol = aNew;
- }
- pCol = &p->aCol[p->def->field_count];
- memset(pCol, 0, sizeof(p->aCol[0]));
struct field_def *column_def = &p->def->fields[p->def->field_count];
memcpy(column_def, &field_def_default, sizeof(field_def_default));
column_def->name = z;
@@ -887,7 +884,6 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
)
{
Table *pTab = pParse->pNewTable;
- Column *pCol = 0;
int iCol = -1, i;
int nTerm;
if (pTab == 0)
@@ -901,8 +897,6 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
pTab->tabFlags |= TF_HasPrimaryKey;
if (pList == 0) {
iCol = pTab->def->field_count - 1;
- pCol = &pTab->aCol[iCol];
- pCol->is_primkey = 1;
nTerm = 1;
} else {
nTerm = pList->nExpr;
@@ -915,21 +909,19 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
goto primary_key_exit;
}
const char *zCName = pCExpr->u.zToken;
- for (iCol = 0;
- iCol < (int)pTab->def->field_count; iCol++) {
- if (strcmp
- (zCName,
- pTab->def->fields[iCol].name) == 0) {
- pCol = &pTab->aCol[iCol];
- pCol->is_primkey = 1;
+ for (uint32_t collumn_id = 0;
+ collumn_id < pTab->def->field_count; collumn_id++) {
+ if (strcmp(zCName,
+ pTab->def->fields[collumn_id].name)
+ == 0) {
+ iCol = collumn_id;
break;
}
}
}
}
- assert(pCol == NULL || pCol == &pTab->aCol[iCol]);
- if (nTerm == 1 && pCol != NULL &&
- (pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER) &&
+ if (nTerm == 1 && iCol != -1 &&
+ pTab->def->fields[iCol].type == FIELD_TYPE_INTEGER &&
sortOrder != SORT_ORDER_DESC) {
assert(autoInc == 0 || autoInc == 1);
pTab->iPKey = iCol;
@@ -998,8 +990,8 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
if (!zColl)
return;
uint32_t *id = &p->def->fields[i].coll_id;
- p->aCol[i].coll = sql_get_coll_seq(pParse, zColl, id);
- if (p->aCol[i].coll != NULL) {
+ p->def->fields[i].coll = sql_get_coll_seq(pParse, zColl, id);
+ if (p->def->fields[i].coll != NULL) {
Index *pIdx;
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
* then an index may have been created on this column before the
@@ -1220,14 +1212,11 @@ identPut(char *z, int *pIdx, char *zSignedIdent)
static char *
createTableStmt(sqlite3 * db, Table * p)
{
- int i, k, n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
- Column *pCol;
- n = 0;
- for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
+ int n = 0;
+ for (uint32_t i = 0; i < p->def->field_count; i++)
n += identLength(p->def->fields[i].name) + 5;
- }
n += identLength(p->def->name);
if (n < 50) {
zSep = "";
@@ -1245,10 +1234,10 @@ createTableStmt(sqlite3 * db, Table * p)
return 0;
}
sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
- k = sqlite3Strlen30(zStmt);
+ int k = sqlite3Strlen30(zStmt);
identPut(zStmt, &k, p->def->name);
zStmt[k++] = '(';
- for (pCol = p->aCol, i = 0; i < (int)p->def->field_count; i++, pCol++) {
+ for (uint32_t i = 0; i < p->def->field_count; i++) {
static const char *const azType[] = {
/* AFFINITY_BLOB */ "",
/* AFFINITY_TEXT */ " TEXT",
@@ -1284,17 +1273,6 @@ createTableStmt(sqlite3 * db, Table * p)
return zStmt;
}
-/* Return true if value x is found any of the first nCol entries of aiCol[]
- */
-static int
-hasColumn(const i16 * aiCol, int nCol, int x)
-{
- while (nCol-- > 0)
- if (x == *(aiCol++))
- return 1;
- return 0;
-}
-
static int
field_def_create_for_pk(struct Parse *parser, struct field_def *field,
const char *space_name)
@@ -1369,7 +1347,7 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
u16 pk_columns = pPk->nColumn;
for (i = j = 0; i < pk_columns; i++) {
uint32_t part_no = pPk->aiColumn[i];
- if (hasColumn(pPk->aiColumn, j, part_no)) {
+ if (index_has_column(pPk->aiColumn, j, part_no)) {
pPk->nColumn--;
} else {
pPk->aiColumn[j++] = part_no;
@@ -1961,12 +1939,9 @@ sql_create_view(struct Parse *parse_context, struct Token *begin,
sqlite3SelectAddColumnTypeAndCollation(parse_context, p,
select);
} else {
- assert(p->aCol == NULL);
assert(sel_tab->def->opts.is_temporary);
p->def->fields = sel_tab->def->fields;
p->def->field_count = sel_tab->def->field_count;
- p->aCol = sel_tab->aCol;
- sel_tab->aCol = NULL;
sel_tab->def->fields = NULL;
sel_tab->def->field_count = 0;
}
diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c
index a185473..2c49e2c 100644
--- a/src/box/sql/resolve.c
+++ b/src/box/sql/resolve.c
@@ -219,7 +219,6 @@ lookupName(Parse * pParse, /* The parsing context */
NameContext *pTopNC = pNC; /* First namecontext in the list */
int isTrigger = 0; /* True if resolved to a trigger column */
Table *pTab = 0; /* Table hold the row */
- Column *pCol; /* A column of pTab */
assert(pNC); /* the name context cannot be NULL. */
assert(zCol); /* The Z in X.Y.Z cannot be NULL */
@@ -272,9 +271,8 @@ lookupName(Parse * pParse, /* The parsing context */
if (0 == (cntTab++)) {
pMatch = pItem;
}
- for (j = 0, pCol = pTab->aCol;
- j < (int)pTab->def->field_count;
- j++, pCol++) {
+ for (j = 0; j < (int)pTab->def->field_count;
+ j++) {
if (strcmp(pTab->def->fields[j].name,
zCol) == 0) {
/* If there has been exactly one prior match and this match
@@ -331,9 +329,8 @@ lookupName(Parse * pParse, /* The parsing context */
if (pTab) {
int iCol;
cntTab++;
- for (iCol = 0, pCol = pTab->aCol;
- iCol < (int)pTab->def->field_count;
- iCol++, pCol++) {
+ for (iCol = 0; iCol <
+ (int)pTab->def->field_count; iCol++) {
if (strcmp(pTab->def->fields[iCol].name,
zCol) == 0) {
if (iCol == pTab->iPKey) {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index ceb7e34..745ae2f 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1811,25 +1811,15 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
{
/* Database connection */
sqlite3 *db = parse->db;
- int i, j; /* Loop counters */
u32 cnt; /* Index added to make the name unique */
- Column *aCol, *pCol; /* For looping over result columns */
- int nCol; /* Number of columns in the result set */
Expr *p; /* Expression for a single result column */
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
sqlite3HashInit(&ht);
- if (expr_list) {
- nCol = expr_list->nExpr;
- aCol = sqlite3DbMallocZero(db, sizeof(aCol[0]) * nCol);
- testcase(aCol == 0);
- } else {
- nCol = 0;
- aCol = NULL;
- }
- assert(nCol == (i16) nCol);
+ uint32_t column_count =
+ (expr_list != NULL) ? (uint32_t)expr_list->nExpr : 0;
/*
* This should be a table without resolved columns.
* sqlite3ViewGetColumnNames could use it to resolve
@@ -1838,21 +1828,21 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
assert(table->def->fields == NULL);
struct region *region = &parse->region;
table->def->fields =
- region_alloc(region, nCol * sizeof(table->def->fields[0]));
+ region_alloc(region,
+ column_count * sizeof(table->def->fields[0]));
if (table->def->fields == NULL) {
sqlite3OomFault(db);
goto cleanup;
}
- for (int i = 0; i < nCol; i++) {
+ for (uint32_t i = 0; i < column_count; i++) {
memcpy(&table->def->fields[i], &field_def_default,
sizeof(field_def_default));
table->def->fields[i].nullable_action = ON_CONFLICT_ACTION_NONE;
table->def->fields[i].is_nullable = true;
}
- table->def->field_count = (uint32_t)nCol;
- table->aCol = aCol;
+ table->def->field_count = column_count;
- for (i = 0, pCol = aCol; i < nCol; i++, pCol++) {
+ for (uint32_t i = 0; i < column_count; i++) {
/* Get an appropriate name for the column
*/
p = sqlite3ExprSkipCollate(expr_list->a[i].pExpr);
@@ -1889,9 +1879,9 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
while (zName && sqlite3HashFind(&ht, zName) != 0) {
nName = sqlite3Strlen30(zName);
if (nName > 0) {
+ int j;
for (j = nName - 1;
- j > 0 && sqlite3Isdigit(zName[j]); j--) {
- }
+ j > 0 && sqlite3Isdigit(zName[j]); j--);
if (zName[j] == ':')
nName = j;
}
@@ -1901,7 +1891,9 @@ sqlite3ColumnsFromExprList(Parse * parse, ExprList * expr_list, Table *table)
sqlite3_randomness(sizeof(cnt), &cnt);
}
size_t name_len = strlen(zName);
- if (zName != NULL && sqlite3HashInsert(&ht, zName, pCol) == pCol)
+ void *field = &table->def->fields[i];
+ if (zName != NULL &&
+ sqlite3HashInsert(&ht, zName, field) == field)
sqlite3OomFault(db);
table->def->fields[i].name =
region_alloc(region, name_len + 1);
@@ -1921,10 +1913,8 @@ cleanup:
* pTable->def could be not temporal in
* sqlite3ViewGetColumnNames so we need clean-up.
*/
- sqlite3DbFree(db, aCol);
table->def->fields = NULL;
table->def->field_count = 0;
- table->aCol = NULL;
rc = SQLITE_NOMEM_BKPT;
}
return rc;
@@ -1949,8 +1939,6 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
{
sqlite3 *db = pParse->db;
NameContext sNC;
- Column *pCol;
- int i;
Expr *p;
struct ExprList_item *a;
@@ -1963,8 +1951,7 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
- for (i = 0, pCol = pTab->aCol;
- i < (int)pTab->def->field_count; i++, pCol++) {
+ for (uint32_t i = 0; i < pTab->def->field_count; i++) {
enum field_type type;
p = a[i].pExpr;
type = columnType(&sNC, p, 0, 0);
@@ -1977,8 +1964,8 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */
bool unused;
uint32_t id;
struct coll *coll = sql_expr_coll(pParse, p, &unused, &id);
- if (coll != NULL && pCol->coll == NULL) {
- pCol->coll = coll;
+ if (coll != NULL && pTab->def->fields[i].coll == NULL) {
+ pTab->def->fields[i].coll = coll;
pTab->def->fields[i].coll_id = id;
}
}
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index c89d256..a67627f 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1872,16 +1872,6 @@ struct Savepoint {
#define SAVEPOINT_RELEASE 1
#define SAVEPOINT_ROLLBACK 2
-/*
- * information about each column of an SQL table is held in an instance
- * of this structure.
- */
-struct Column {
- /** Collating sequence. */
- struct coll *coll;
- u8 is_primkey; /* Boolean propertie for being PK */
-};
-
#define sqlite3IsNumericAffinity(X) ((X)>=AFFINITY_NUMERIC)
/*
@@ -1910,7 +1900,6 @@ struct Column {
* by an instance of the following structure.
*/
struct Table {
- Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
@@ -4418,6 +4407,18 @@ void sqlite3FileSuffix3(const char *, char *);
#endif
u8 sqlite3GetBoolean(const char *z, u8);
+/**
+ * Test if @column_idx is a part of first @parts_count of index.
+ *
+ * @param parts pointer to array with columns representing index.
+ * @param parts_count count of index parts.
+ * @column_idx index of column to test.
+ * @retval true if index contains column_idx.
+ * @retval false else.
+ */
+bool
+index_has_column(const i16 *parts, int parts_count, int column_idx);
+
const void *sqlite3ValueText(sqlite3_value *);
int sqlite3ValueBytes(sqlite3_value *);
void sqlite3ValueSetStr(sqlite3_value *, int, const void *,
--
2.7.4
More information about the Tarantool-patches
mailing list