From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id BADC62177D for ; Sat, 28 Apr 2018 14:27:12 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id E-uH-SI77gDD for ; Sat, 28 Apr 2018 14:27:12 -0400 (EDT) Received: from smtpng3.m.smailru.net (smtpng3.m.smailru.net [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 322D6215BE for ; Sat, 28 Apr 2018 14:27:12 -0400 (EDT) From: Kirill Shcherbatov Subject: [tarantool-patches] [PATCH v4 7/7] sql: space_def* instead of Table* in Expr Date: Sat, 28 Apr 2018 21:26:58 +0300 Message-Id: <5ec6ab0d77b24efbed08699c96afd04bd0cf0739.1524939875.git.kshcherbatov@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, Kirill Shcherbatov Part of #3272. --- src/box/field_def.c | 1 + src/box/field_def.h | 5 ++++ src/box/sql.c | 10 ++++---- src/box/sql/build.c | 48 ++++++++++++++++++++------------------ src/box/sql/delete.c | 4 ++-- src/box/sql/expr.c | 61 ++++++++++++++++++++++++++----------------------- src/box/sql/fkey.c | 13 +++++------ src/box/sql/insert.c | 24 ++++++++++--------- src/box/sql/pragma.c | 8 ++++--- src/box/sql/resolve.c | 10 ++++---- src/box/sql/select.c | 26 +++++++++++++-------- src/box/sql/sqliteInt.h | 21 +++++++++-------- src/box/sql/update.c | 29 +++++++++++------------ src/box/sql/vdbeaux.c | 20 ++++++---------- src/box/sql/where.c | 13 +++++++---- src/box/sql/wherecode.c | 18 +++++++++------ src/box/sql/whereexpr.c | 2 +- 17 files changed, 167 insertions(+), 146 deletions(-) diff --git a/src/box/field_def.c b/src/box/field_def.c index 010b3b7..63aab46 100644 --- a/src/box/field_def.c +++ b/src/box/field_def.c @@ -100,6 +100,7 @@ const struct opt_def field_def_reg[] = { const struct field_def field_def_default = { .type = FIELD_TYPE_ANY, + .affinity = 0, .name = NULL, .is_nullable = false, .nullable_action = ON_CONFLICT_ACTION_DEFAULT, diff --git a/src/box/field_def.h b/src/box/field_def.h index dfc1950..4577f6b 100644 --- a/src/box/field_def.h +++ b/src/box/field_def.h @@ -102,6 +102,11 @@ struct field_def { * then UNKNOWN is stored for it. */ enum field_type type; + /** + * Affinity type for comparations in SQL. + * FIXME: Remove affinity after types redesign in SQL. + */ + char affinity; /** 0-terminated field name. */ char *name; /** True, if a field can store NULL. */ diff --git a/src/box/sql.c b/src/box/sql.c index 9f5a124..11ec0b1 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -1428,7 +1428,6 @@ static const char *convertSqliteAffinity(int affinity, bool allow_nulls) */ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf) { - struct Column *aCol = pTable->aCol; const struct Enc *enc = get_enc(buf); const struct space_def *def = pTable->def; assert(def != NULL); @@ -1471,8 +1470,9 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf) if (i == pk_forced_int) { t = "integer"; } else { - t = aCol[i].affinity == SQLITE_AFF_BLOB ? "scalar" : - convertSqliteAffinity(aCol[i].affinity, + char affinity = def->fields[i].affinity; + t = affinity == SQLITE_AFF_BLOB ? "scalar" : + convertSqliteAffinity(affinity, def->fields[i].is_nullable); } p = enc->encode_str(p, t, strlen(t)); @@ -1532,7 +1532,6 @@ int tarantoolSqlite3MakeTableOpts(Table *pTable, const char *zSql, void *buf) */ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf) { - struct Column *aCol = pIndex->pTable->aCol; struct space_def *def = pIndex->pTable->def; assert(def != NULL); @@ -1569,7 +1568,8 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf) if (pk_forced_int == col) { t = "integer"; } else { - t = convertSqliteAffinity(aCol[col].affinity, + char affinity = def->fields[col].affinity; + t = convertSqliteAffinity(affinity, def->fields[col].is_nullable); } /* do not decode default collation */ diff --git a/src/box/sql/build.c b/src/box/sql/build.c index a98a6bd..742f8a5 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -701,7 +701,7 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType) * TODO: since SQL standard prohibits column creation without * specified type, the code below should emit an error. */ - pCol->affinity = SQLITE_AFF_BLOB; + column_def->affinity = SQLITE_AFF_BLOB; pCol->szEst = 1; column_def->type = FIELD_TYPE_SCALAR; } else { @@ -712,14 +712,14 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType) pType->n == 7) || (sqlite3StrNICmp(pType->z, "INT", 3) == 0 && pType->n == 3)) { - pCol->affinity = SQLITE_AFF_INTEGER; + column_def->affinity = SQLITE_AFF_INTEGER; column_def->type = FIELD_TYPE_INTEGER; } else { zType = sqlite3_malloc(pType->n + 1); memcpy(zType, pType->z, pType->n); zType[pType->n] = 0; sqlite3Dequote(zType); - pCol->affinity = sqlite3AffinityType(zType, 0); + column_def->affinity = sqlite3AffinityType(zType, 0); sqlite3_free(zType); column_def->type = FIELD_TYPE_SCALAR; } @@ -1032,8 +1032,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken) */ for (pIdx = p->pIndex; pIdx; pIdx = pIdx->pNext) { assert(pIdx->nColumn == 1); - if (pIdx->aiColumn[0] == i) - pIdx->coll_array[0] = sql_column_collation(p, i); + if (pIdx->aiColumn[0] == i) { + pIdx->coll_array[0] = + sql_column_collation(p->def, i); + } } } } @@ -1046,10 +1048,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken) * @retval Pointer to collation. */ struct coll * -sql_column_collation(Table *table, uint32_t column) +sql_column_collation(struct space_def *def, uint32_t column) { - assert(table != NULL); - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum); + assert(def != NULL); + uint32_t space_id = def->id; struct space *space = space_by_id(space_id); /* * It is not always possible to fetch collation directly @@ -1064,9 +1066,9 @@ sql_column_collation(Table *table, uint32_t column) * SQL specific structures. */ if (space == NULL || space_index(space, 0) == NULL) { - assert(column < (uint32_t)table->def->field_count); + assert(column < (uint32_t)def->field_count); struct coll *coll = - coll_by_id(table->def->fields[column].coll_id); + coll_by_id(def->fields[column].coll_id); return coll; } @@ -1322,18 +1324,19 @@ createTableStmt(sqlite3 * db, Table * p) k += sqlite3Strlen30(&zStmt[k]); zSep = zSep2; identPut(zStmt, &k, p->def->fields[i].name); - assert(pCol->affinity - SQLITE_AFF_BLOB >= 0); - assert(pCol->affinity - SQLITE_AFF_BLOB < ArraySize(azType)); - testcase(pCol->affinity == SQLITE_AFF_BLOB); - testcase(pCol->affinity == SQLITE_AFF_TEXT); - testcase(pCol->affinity == SQLITE_AFF_NUMERIC); - testcase(pCol->affinity == SQLITE_AFF_INTEGER); - testcase(pCol->affinity == SQLITE_AFF_REAL); - - zType = azType[pCol->affinity - SQLITE_AFF_BLOB]; + char affinity = p->def->fields[i].affinity; + assert(affinity - SQLITE_AFF_BLOB >= 0); + assert(affinity - SQLITE_AFF_BLOB < ArraySize(azType)); + testcase(affinity == SQLITE_AFF_BLOB); + testcase(affinity == SQLITE_AFF_TEXT); + testcase(affinity == SQLITE_AFF_NUMERIC); + testcase(affinity == SQLITE_AFF_INTEGER); + testcase(affinity == SQLITE_AFF_REAL); + + zType = azType[affinity - SQLITE_AFF_BLOB]; len = sqlite3Strlen30(zType); - assert(pCol->affinity == SQLITE_AFF_BLOB - || pCol->affinity == sqlite3AffinityType(zType, 0)); + assert(affinity == SQLITE_AFF_BLOB + || affinity == sqlite3AffinityType(zType, 0)); memcpy(&zStmt[k], zType, len); k += len; assert(k <= n); @@ -1843,6 +1846,7 @@ sqlite3EndTable(Parse * pParse, /* Parse context */ */ if (db->init.busy) p->tnum = db->init.newTnum; + p->def->id = SQLITE_PAGENO_TO_SPACEID(p->tnum); assert(p->def->opts.is_view == (p->pSelect != NULL)); if (!p->def->opts.is_view) { @@ -3094,7 +3098,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */ goto exit_create_index; } } else if (j >= 0) { - coll = sql_column_collation(pTab, j); + coll = sql_column_collation(pTab->def, j); } else { coll = NULL; } diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c index 37baca2..5056005 100644 --- a/src/box/sql/delete.c +++ b/src/box/sql/delete.c @@ -431,7 +431,7 @@ sqlite3DeleteFrom(Parse * pParse, /* The parser context */ if (!isView) { for (i = 0; i < nPk; i++) { assert(pPk->aiColumn[i] >= 0); - sqlite3ExprCodeGetColumnOfTable(v, pTab, + sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iTabCur, pPk-> aiColumn[i], @@ -747,7 +747,7 @@ sqlite3GenerateRowDelete(Parse * pParse, /* Parsing context */ testcase(mask != 0xffffffff && iCol == 32); if (mask == 0xffffffff || (iCol <= 31 && (mask & MASKBIT32(iCol)) != 0)) { - sqlite3ExprCodeGetColumnOfTable(v, pTab, + sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iDataCur, iCol, iOld + iCol + 1); diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 119940c..4e20098 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -46,10 +46,11 @@ static int exprCodeVector(Parse * pParse, Expr * p, int *piToFree); * Return the affinity character for a single column of a table. */ char -sqlite3TableColumnAffinity(Table * pTab, int iCol) +sqlite3TableColumnAffinity(struct space_def *def, int iCol) { - assert(iCol < (int)pTab->def->field_count); - return iCol >= 0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER; + assert(iCol < (int)def->field_count); + return iCol >= 0 ? def->fields[iCol].affinity : + SQLITE_AFF_INTEGER; } /* @@ -90,7 +91,8 @@ sqlite3ExprAffinity(Expr * pExpr) } #endif if (op == TK_AGG_COLUMN || op == TK_COLUMN) { - return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + return sqlite3TableColumnAffinity(pExpr->space_def, + pExpr->iColumn); } if (op == TK_SELECT_COLUMN) { assert(pExpr->pLeft->flags & EP_xIsSelect); @@ -179,13 +181,13 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_found) } if ((op == TK_AGG_COLUMN || op == TK_COLUMN || op == TK_REGISTER || op == TK_TRIGGER) && - p->pTab != 0) { + p->space_def != 0) { /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally * a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if (j >= 0) { - coll = sql_column_collation(p->pTab, j); + coll = sql_column_collation(p->space_def, j); *is_found = true; } break; @@ -2132,10 +2134,10 @@ sqlite3ExprCanBeNull(const Expr * p) case TK_BLOB: return 0; case TK_COLUMN: - assert(p->pTab != 0); + assert(p->space_def!= 0); return ExprHasProperty(p, EP_CanBeNull) || (p->iColumn >= 0 - && table_column_is_nullable(p->pTab, p->iColumn)); + && table_column_is_nullable(p->space_def, p->iColumn)); default: return 1; } @@ -2435,7 +2437,9 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */ for (i = 0; i < nExpr && affinity_ok; i++) { Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); int iCol = pEList->a[i].pExpr->iColumn; - char idxaff = sqlite3TableColumnAffinity(pTab, iCol); /* RHS table */ + /* RHS table */ + char idxaff = + sqlite3TableColumnAffinity(pTab->def, iCol); char cmpaff = sqlite3CompareAffinity(pLhs, idxaff); testcase(cmpaff == SQLITE_AFF_BLOB); testcase(cmpaff == SQLITE_AFF_TEXT); @@ -3175,8 +3179,9 @@ sqlite3ExprCodeIN(Parse * pParse, /* Parsing and code generating context */ struct Index *pk = sqlite3PrimaryKeyIndex(tab); assert(pk); + char affinity = tab->def->fields[pk->aiColumn[0]].affinity; if (pk->nColumn == 1 - && tab->aCol[pk->aiColumn[0]].affinity == 'D' + && affinity == 'D' && pk->aiColumn[0] < nVector) { int reg_pk = rLhs + pk->aiColumn[0]; sqlite3VdbeAddOp2(v, OP_MustBeInt, reg_pk, destIfFalse); @@ -3519,7 +3524,7 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse, /* The parsing context */ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); } else { - sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, + sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable->def, iTabCur, iTabCol, regOut); } } @@ -3529,7 +3534,7 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse, /* The parsing context */ */ void sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */ - Table * pTab, /* The table containing the value */ + struct space_def *space_def, int iTabCur, /* The PK cursor */ int iCol, /* Index of the column to extract */ int regOut /* Extract the value into this register */ @@ -3537,7 +3542,7 @@ sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */ { sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut); if (iCol >= 0) { - sqlite3ColumnDefault(v, pTab, iCol, regOut); + sqlite3ColumnDefault(v, space_def, iCol, regOut); } } @@ -3552,7 +3557,7 @@ sqlite3ExprCodeGetColumnOfTable(Vdbe * v, /* The VDBE under construction */ */ int sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context */ - Table * pTab, /* Description of the table we are reading from */ + struct space_def * space_def, int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg, /* Store results here */ @@ -3572,7 +3577,7 @@ sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context } } assert(v != 0); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); + sqlite3ExprCodeGetColumnOfTable(v, space_def, iTable, iColumn, iReg); if (p5) { sqlite3VdbeChangeP5(v, p5); } else { @@ -3583,14 +3588,14 @@ sqlite3ExprCodeGetColumn(Parse * pParse, /* Parsing and code generating context void sqlite3ExprCodeGetColumnToReg(Parse * pParse, /* Parsing and code generating context */ - Table * pTab, /* Description of the table we are reading from */ + struct space_def * space_def, int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg /* Store results here */ ) { int r1 = - sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); + sqlite3ExprCodeGetColumn(pParse, space_def, iColumn, iTable, iReg, 0); if (r1 != iReg) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); } @@ -3777,7 +3782,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target) iTab = pParse->iSelfTab; } } - return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->space_def, pExpr->iColumn, iTab, target, pExpr->op2); } @@ -4241,23 +4246,21 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target) * p1==1 -> old.a p1==4 -> new.a * p1==2 -> old.b p1==5 -> new.b */ - Table *pTab = pExpr->pTab; + struct space_def *def = pExpr->space_def; int p1 = - pExpr->iTable * (pTab->def->field_count + 1) + 1 + + pExpr->iTable * (def->field_count + 1) + 1 + pExpr->iColumn; assert(pExpr->iTable == 0 || pExpr->iTable == 1); assert(pExpr->iColumn >= 0 - && pExpr->iColumn < (int)pTab->def->field_count); - assert(pTab->iPKey < 0 - || pExpr->iColumn != pTab->iPKey); + && pExpr->iColumn < (int)def->field_count); assert(p1 >= 0 && p1 < - ((int)pTab->def->field_count * 2 + 2)); + ((int)def->field_count * 2 + 2)); sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "%s.%s -> $%d", (pExpr->iTable ? "new" : "old"), - pExpr->pTab->def->fields[pExpr->iColumn].name, + def->fields[pExpr->iColumn].name, target)); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -4267,9 +4270,9 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target) * EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to * floating point when extracting it from the record. */ + char affinity = def->fields[pExpr->iColumn].affinity; if (pExpr->iColumn >= 0 - && pTab->aCol[pExpr->iColumn].affinity == - SQLITE_AFF_REAL) { + && affinity == SQLITE_AFF_REAL) { sqlite3VdbeAddOp1(v, OP_RealAffinity, target); } #endif @@ -5440,8 +5443,8 @@ analyzeAggregate(Walker * pWalker, Expr * pExpr) pAggInfo)) >= 0) { pCol = &pAggInfo->aCol[k]; - pCol->pTab = - pExpr->pTab; + pCol->space_def = + pExpr->space_def; pCol->iTable = pExpr->iTable; pCol->iColumn = diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c index 16f72d8..52f86d4 100644 --- a/src/box/sql/fkey.c +++ b/src/box/sql/fkey.c @@ -299,7 +299,7 @@ sqlite3FkLocateIndex(Parse * pParse, /* Parse context to store any error in */ * unusable. Bail out early in this case. */ struct coll *def_coll; - def_coll = sql_column_collation(pParent, + def_coll = sql_column_collation(pParent->def, iCol); struct coll *coll; coll = sql_index_collation(pIdx, i); @@ -527,15 +527,14 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */ ) { Expr *pExpr; - Column *pCol; sqlite3 *db = pParse->db; pExpr = sqlite3Expr(db, TK_REGISTER, 0); if (pExpr) { if (iCol >= 0 && iCol != pTab->iPKey) { - pCol = &pTab->aCol[iCol]; pExpr->iTable = regBase + iCol + 1; - pExpr->affinity = pCol->affinity; + char affinity = pTab->def->fields[iCol].affinity; + pExpr->affinity = affinity; const char *coll_name = "binary"; pExpr = sqlite3ExprAddCollateString(pParse, pExpr, coll_name); @@ -553,14 +552,14 @@ exprTableRegister(Parse * pParse, /* Parsing and code generating context */ */ static Expr * exprTableColumn(sqlite3 * db, /* The database connection */ - Table * pTab, /* The table whose column is desired */ + struct space_def *def, int iCursor, /* The open cursor on the table */ i16 iCol /* The column that is wanted */ ) { Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if (pExpr) { - pExpr->pTab = pTab; + pExpr->space_def = def; pExpr->iTable = iCursor; pExpr->iColumn = iCol; } @@ -673,7 +672,7 @@ fkScanChildren(Parse * pParse, /* Parse context */ i16 iCol = pIdx->aiColumn[i]; assert(iCol >= 0); pLeft = exprTableRegister(pParse, pTab, regData, iCol); - pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, + pRight = exprTableColumn(db, pTab->def, pSrc->a[0].iCursor, iCol); pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight); pAll = sqlite3ExprAnd(db, pAll, pEq); diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c index bde0cc1..7c21359 100644 --- a/src/box/sql/insert.c +++ b/src/box/sql/insert.c @@ -90,7 +90,6 @@ sqlite3IndexAffinityStr(sqlite3 * db, Index * pIdx) */ int n; int nColumn = index_column_count(pIdx); - Table *pTab = pIdx->pTable; pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, nColumn + 1); if (!pIdx->zColAff) { @@ -100,7 +99,9 @@ sqlite3IndexAffinityStr(sqlite3 * db, Index * pIdx) for (n = 0; n < nColumn; n++) { i16 x = pIdx->aiColumn[n]; if (x >= 0) { - pIdx->zColAff[n] = pTab->aCol[x].affinity; + char affinity = pIdx->pTable-> + def->fields[x].affinity; + pIdx->zColAff[n] = affinity; } else { char aff; assert(x == XN_EXPR); @@ -154,7 +155,8 @@ sqlite3TableAffinity(Vdbe * v, Table * pTab, int iReg) } for (i = 0; i < (int)pTab->def->field_count; i++) { - zColAff[i] = pTab->aCol[i].affinity; + char affinity = pTab->def->fields[i].affinity; + zColAff[i] = affinity; } do { zColAff[i--] = 0; @@ -1115,7 +1117,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse, /* The parser context */ /* Don't bother checking for NOT NULL on columns that do not change */ continue; } - if (table_column_is_nullable(pTab, i) + if (table_column_is_nullable(pTab->def, i) || (pTab->tabFlags & TF_Autoincrement && pTab->iAutoIncPKey == i)) continue; /* This column is allowed to be NULL */ @@ -1805,17 +1807,17 @@ xferOptimization(Parse * pParse, /* Parser context */ return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ } for (i = 0; i < (int)pDest->def->field_count; i++) { - Column *pDestCol = &pDest->aCol[i]; - Column *pSrcCol = &pSrc->aCol[i]; - if (pDestCol->affinity != pSrcCol->affinity) { + char pdest_affinity = pDest->def->fields[i].affinity; + char psrc_affinity = pSrc->def->fields[i].affinity; + if (pdest_affinity != psrc_affinity) { return 0; /* Affinity must be the same on all columns */ } - if (sql_column_collation(pDest, i) != - sql_column_collation(pSrc, i)) { + if (sql_column_collation(pDest->def, i) != + sql_column_collation(pSrc->def, i)) { return 0; /* Collating sequence must be the same on all columns */ } - if (!table_column_is_nullable(pDest, i) - && table_column_is_nullable(pSrc, i)) { + if (!table_column_is_nullable(pDest->def, i) + && table_column_is_nullable(pSrc->def, i)) { return 0; /* tab2 must be NOT NULL if tab1 is */ } /* Default values for second and subsequent columns need to match. */ diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c index 463bb7e..c49817f 100644 --- a/src/box/sql/pragma.c +++ b/src/box/sql/pragma.c @@ -373,7 +373,9 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ i; k++) { } } - bool nullable = table_column_is_nullable(pTab, i); + bool nullable = + table_column_is_nullable(pTab->def, + i); uint32_t space_id = SQLITE_PAGENO_TO_SPACEID( pTab->tnum); @@ -691,7 +693,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ iKey, regRow); sqlite3ColumnDefault(v, - pTab, + pTab->def, iKey, regRow); sqlite3VdbeAddOp2(v, @@ -708,7 +710,7 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */ } else { for (j = 0; j < pFK->nCol; j++) { sqlite3ExprCodeGetColumnOfTable - (v, pTab, 0, + (v, pTab->def, 0, aiCols ? aiCols[j] : pFK->aCol[j]. iFrom, regRow + j); diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c index 5d85ef7..f24399c 100644 --- a/src/box/sql/resolve.c +++ b/src/box/sql/resolve.c @@ -227,7 +227,7 @@ lookupName(Parse * pParse, /* The parsing context */ /* Initialize the node to no-match */ pExpr->iTable = -1; - pExpr->pTab = 0; + pExpr->space_def = NULL; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Start at the inner-most context and move outward until a match is found */ @@ -301,7 +301,7 @@ lookupName(Parse * pParse, /* The parsing context */ } if (pMatch) { pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; + pExpr->space_def = pMatch->pTab->def; /* RIGHT JOIN not (yet) supported */ assert((pMatch->fg.jointype & JT_RIGHT) == 0); if ((pMatch->fg.jointype & JT_LEFT) != 0) { @@ -365,7 +365,7 @@ lookupName(Parse * pParse, /* The parsing context */ : (((u32) 1) << iCol)); } pExpr->iColumn = (i16) iCol; - pExpr->pTab = pTab; + pExpr->space_def = pTab->def; isTrigger = 1; } } @@ -499,9 +499,9 @@ sqlite3CreateColumnExpr(sqlite3 * db, SrcList * pSrc, int iSrc, int iCol) Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if (p) { struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; + p->space_def = pItem->pTab->def; p->iTable = pItem->iCursor; - if (p->pTab->iPKey == iCol) { + if (pItem->pTab->iPKey == iCol) { p->iColumn = -1; } else { p->iColumn = (ynVar) iCol; diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 34d296d..ff9f18b 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -1636,7 +1636,7 @@ columnTypeImpl(NameContext * pNC, Expr * pExpr, break; } - assert(pTab && pExpr->pTab == pTab); + assert(pTab && pExpr->space_def == pTab->def); if (pS) { /* The "table" is actually a sub-select or a view in the FROM clause * of the SELECT statement. Return the declaration type and origin @@ -1842,19 +1842,23 @@ sqlite3ColumnsFromExprList(Parse * pParse, /* Parsing context */ /* If the column contains an "AS " phrase, use as the name */ } else { Expr *pColExpr = p; /* The expression that is the result column name */ - Table *pTab; /* Table associated with this expression */ + struct space_def *space_def; while (pColExpr->op == TK_DOT) { pColExpr = pColExpr->pRight; assert(pColExpr != 0); } if (pColExpr->op == TK_COLUMN - && ALWAYS(pColExpr->pTab != 0)) { + && ALWAYS(pColExpr->space_def != NULL)) { /* For columns use the column name name */ int iCol = pColExpr->iColumn; - pTab = pColExpr->pTab; + space_def = pColExpr->space_def; + Table *pTable = + sqlite3LocateTable(pParse, 0, + space_def->name); + assert(pTable != NULL); if (iCol < 0) - iCol = pTab->iPKey; - zName = pTab->def->fields[iCol].name; + iCol = pTable->iPKey; + zName = space_def->fields[iCol].name; } else if (pColExpr->op == TK_ID) { assert(!ExprHasProperty(pColExpr, EP_IntValue)); zName = pColExpr->u.zToken; @@ -1946,11 +1950,13 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse, /* Parsing contexts */ p = a[i].pExpr; type = columnType(&sNC, p, 0, 0, 0, &pCol->szEst); szAll += pCol->szEst; - pCol->affinity = sqlite3ExprAffinity(p); pTab->def->fields[i].type = type; - if (pCol->affinity == 0) - pCol->affinity = SQLITE_AFF_BLOB; + char affinity = sqlite3ExprAffinity(p); + if (affinity == 0) + affinity = SQLITE_AFF_BLOB; + pTab->def->fields[i].affinity = affinity; + bool unused; struct coll *coll = sql_expr_coll(pParse, p, &unused); if (coll != NULL && pTab->def->fields[i].coll_id == COLL_NONE) @@ -5931,7 +5937,7 @@ sqlite3Select(Parse * pParse, /* The parser context */ if (pCol->iSorterColumn >= j) { int r1 = j + regBase; sqlite3ExprCodeGetColumnToReg - (pParse, pCol->pTab, + (pParse, pCol->space_def, pCol->iColumn, pCol->iTable, r1); j++; diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h index 6eddbec..4c2c6fb 100644 --- a/src/box/sql/sqliteInt.h +++ b/src/box/sql/sqliteInt.h @@ -1867,7 +1867,6 @@ struct Savepoint { * of this structure. */ struct Column { - char affinity; /* One of the SQLITE_AFF_... values */ u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */ u8 is_primkey; /* Boolean propertie for being PK */ }; @@ -2226,7 +2225,8 @@ struct AggInfo { int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */ ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ - Table *pTab; /* Source table */ + /* Pointer to space definition. */ + struct space_def *space_def; int iTable; /* Cursor number of the source table */ int iColumn; /* Column number within the source table */ int iSorterColumn; /* Column number in the sorting index */ @@ -2361,7 +2361,8 @@ struct Expr { * TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. */ + /* Pointer for table relative definition. */ + struct space_def *space_def; }; /* @@ -3520,7 +3521,7 @@ void sqlite3AddCollateType(Parse *, Token *); const char * column_collation_name(Table *, uint32_t); struct coll * -sql_column_collation(Table *, uint32_t); +sql_column_collation(struct space_def *, uint32_t); const char * index_collation_name(Index *, uint32_t); struct coll * @@ -3607,9 +3608,9 @@ int sqlite3WhereOkOnePass(WhereInfo *, int *); #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ void sqlite3ExprCodeLoadIndexColumn(Parse *, Index *, int, int, int); -int sqlite3ExprCodeGetColumn(Parse *, Table *, int, int, int, u8); -void sqlite3ExprCodeGetColumnToReg(Parse *, Table *, int, int, int); -void sqlite3ExprCodeGetColumnOfTable(Vdbe *, Table *, int, int, int); +int sqlite3ExprCodeGetColumn(Parse *, struct space_def *, int, int, int, u8); +void sqlite3ExprCodeGetColumnToReg(Parse *, struct space_def *, int, int, int); +void sqlite3ExprCodeGetColumnOfTable(Vdbe *, struct space_def *, int, int, int); void sqlite3ExprCodeMove(Parse *, int, int, int); void sqlite3ExprCacheStore(Parse *, int, int, int); void sqlite3ExprCachePush(Parse *); @@ -3802,7 +3803,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *, Index *); void sqlite3TableAffinity(Vdbe *, Table *, int); char sqlite3CompareAffinity(Expr * pExpr, char aff2); int sqlite3IndexAffinityOk(Expr * pExpr, char idx_affinity); -char sqlite3TableColumnAffinity(Table *, int); +char sqlite3TableColumnAffinity(struct space_def *, int); char sqlite3ExprAffinity(Expr * pExpr); int sqlite3Atoi64(const char *, i64 *, int); int sqlite3DecOrHexToI64(const char *, i64 *); @@ -3890,7 +3891,7 @@ int sqlite3ResolveExprListNames(NameContext *, ExprList *); void sqlite3ResolveSelectNames(Parse *, Select *, NameContext *); void sqlite3ResolveSelfReference(Parse *, Table *, int, Expr *, ExprList *); int sqlite3ResolveOrderGroupBy(Parse *, Select *, ExprList *, const char *); -void sqlite3ColumnDefault(Vdbe *, Table *, int, int); +void sqlite3ColumnDefault(Vdbe *, struct space_def *, int, int); void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); char* rename_table(sqlite3 *, const char *, const char *, bool *); @@ -4141,6 +4142,6 @@ enum on_conflict_action table_column_nullable_action(struct Table *tab, uint32_t column); bool -table_column_is_nullable(struct Table *tab, uint32_t column); +table_column_is_nullable(struct space_def *def, uint32_t column); #endif /* SQLITEINT_H */ diff --git a/src/box/sql/update.c b/src/box/sql/update.c index 2f36423..38f824f 100644 --- a/src/box/sql/update.c +++ b/src/box/sql/update.c @@ -69,30 +69,27 @@ * space. */ void -sqlite3ColumnDefault(Vdbe * v, Table * pTab, int i, int iReg) +sqlite3ColumnDefault(Vdbe * v, struct space_def * def, int i, int iReg) { - assert(pTab != 0); - assert(pTab->def->opts.is_view == (pTab->pSelect != NULL)); - if (!pTab->def->opts.is_view) { + assert(def != NULL); + if (!def->opts.is_view) { sqlite3_value *pValue = 0; - Column *pCol = &pTab->aCol[i]; - VdbeComment((v, "%s.%s", pTab->def->name, - pTab->def->fields[i].name)); - assert(i < (int)pTab->def->field_count); + char affinity = def->fields[i].affinity; + VdbeComment((v, "%s.%s", def->name, def->fields[i].name)); + assert(i < (int)def->field_count); Expr *expr = NULL; struct space *space = - space_cache_find(SQLITE_PAGENO_TO_SPACEID(pTab->tnum)); + space_cache_find(def->id); if (space != NULL && space->def->fields != NULL) expr = space->def->fields[i].default_value_expr; sqlite3ValueFromExpr(sqlite3VdbeDb(v), - expr, - pCol->affinity, &pValue); + expr, affinity, &pValue); if (pValue) { sqlite3VdbeAppendP4(v, pValue, P4_MEM); } #ifndef SQLITE_OMIT_FLOATING_POINT - if (pTab->aCol[i].affinity == SQLITE_AFF_REAL) { + if (affinity == SQLITE_AFF_REAL) { sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); } #endif @@ -381,7 +378,7 @@ sqlite3Update(Parse * pParse, /* The parser context */ } else { for (i = 0; i < nPk; i++) { assert(pPk->aiColumn[i] >= 0); - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, + sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iDataCur, pPk->aiColumn[i], iPk + i); } @@ -486,7 +483,7 @@ sqlite3Update(Parse * pParse, /* The parser context */ || (i < 32 && (oldmask & MASKBIT32(i)) != 0) || table_column_is_in_pk(pTab, i)) { testcase(oldmask != 0xffffffff && i == 31); - sqlite3ExprCodeGetColumnOfTable(v, pTab, + sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iDataCur, i, regOld + i); } else { @@ -529,7 +526,7 @@ sqlite3Update(Parse * pParse, /* The parser context */ */ testcase(i == 31); testcase(i == 32); - sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, + sqlite3ExprCodeGetColumnToReg(pParse, pTab->def, i, iDataCur, regNew + i); } else { @@ -570,7 +567,7 @@ sqlite3Update(Parse * pParse, /* The parser context */ */ for (i = 0; i < (int)pTab->def->field_count; i++) { if (aXRef[i] < 0 && i != pTab->iPKey) { - sqlite3ExprCodeGetColumnOfTable(v, pTab, + sqlite3ExprCodeGetColumnOfTable(v, pTab->def, iDataCur, i, regNew + i); } diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index f76c689..f9927ed 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -4724,28 +4724,22 @@ table_column_nullable_action(struct Table *tab, uint32_t column) * @return return nullability flag value */ bool -table_column_is_nullable(struct Table *tab, uint32_t column) +table_column_is_nullable(struct space_def *def, uint32_t column) { /* Temporary hack: until Tarantoool's ephemeral spaces are on-boarded, * views are not handled properly in Tarantool as well. */ - if (!(tab->tabFlags | TF_Ephemeral || space_is_view(tab))) { - uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(tab->tnum); - struct space *space = space_cache_find(space_id); - - assert(space); - + struct space *space = space_cache_find(def->id); + if (space != NULL && !space->def->opts.is_view) { struct tuple_format *format = space->format; - assert(format); assert(format->field_count > column); - return format->fields[column].nullable_action == - ON_CONFLICT_ACTION_NONE; + ON_CONFLICT_ACTION_NONE; } else { /* tab is ephemeral (in SQLite sense). */ - assert(tab->def->fields[column].is_nullable == - (tab->def->fields[column].nullable_action == + assert(def->fields[column].is_nullable == + (def->fields[column].nullable_action == ON_CONFLICT_ACTION_NONE)); - return tab->def->fields[column].is_nullable; + return def->fields[column].is_nullable; } } diff --git a/src/box/sql/where.c b/src/box/sql/where.c index 88f4c28..d33fd9c 100644 --- a/src/box/sql/where.c +++ b/src/box/sql/where.c @@ -378,7 +378,9 @@ whereScanInit(WhereScan * pScan, /* The WhereScan object being initialized */ if (iColumn == XN_EXPR) { pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; } else if (iColumn >= 0) { - pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; + char affinity = + pIdx->pTable->def->fields[iColumn].affinity; + pScan->idxaff = affinity; pScan->coll = sql_index_collation(pIdx, j); pScan->is_column_seen = true; } @@ -491,7 +493,7 @@ indexColumnNotNull(Index * pIdx, int iCol) assert(iCol >= 0 && iCol < (int)index_column_count(pIdx)); j = pIdx->aiColumn[iCol]; if (j >= 0) { - return !table_column_is_nullable(pIdx->pTable, j); + return !table_column_is_nullable(pIdx->pTable->def, j); } else if (j == (-1)) { return 1; } else { @@ -2237,7 +2239,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */ aff = sqlite3CompareAffinity(pRhs, sqlite3ExprAffinity(pLhs)); idxaff = - sqlite3TableColumnAffinity(pIdx->pTable, pLhs->iColumn); + sqlite3TableColumnAffinity(pIdx->pTable->def, + pLhs->iColumn); if (aff != idxaff) break; @@ -3331,8 +3334,8 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, /* The WHERE clause */ if (isOrderDistinct && iColumn >= 0 && j >= pLoop->nEq - && table_column_is_nullable(pIndex->pTable, - iColumn)) { + && table_column_is_nullable( + pIndex->pTable->def, iColumn)) { isOrderDistinct = 0; } diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c index 3da7cdb..3459020 100644 --- a/src/box/sql/wherecode.c +++ b/src/box/sql/wherecode.c @@ -909,7 +909,7 @@ codeCursorHintFixExpr(Walker * pWalker, Expr * pExpr) if (pExpr->iTable != pHint->iTabCur) { Vdbe *v = pWalker->pParse->pVdbe; int reg = ++pWalker->pParse->nMem; /* Register for column value */ - sqlite3ExprCodeGetColumnOfTable(v, pExpr->pTab, + sqlite3ExprCodeGetColumnOfTable(v, pExpr->pTab->def, pExpr->iTable, pExpr->iColumn, reg); pExpr->op = TK_REGISTER; @@ -1261,8 +1261,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t * FYI: entries in an index are ordered as follows: * NULL, ... NULL, min_value, ... */ - if ((j >= 0 && table_column_is_nullable(pIdx->pTable, j)) - || j == XN_EXPR) { + if ((j >= 0 && + table_column_is_nullable(pIdx->pTable->def, j)) || + j == XN_EXPR) { assert(pLoop->nSkip == 0); bSeekPastNull = 1; nExtraReg = 1; @@ -1308,7 +1309,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t if (pRangeStart == 0) { j = pIdx->aiColumn[nEq]; if ((j >= 0 - && table_column_is_nullable(pIdx->pTable, j)) || j == XN_EXPR) { + && table_column_is_nullable( + pIdx->pTable->def, j)) || + j == XN_EXPR) { bSeekPastNull = 1; } } @@ -1387,8 +1390,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t struct Index *pk = sqlite3PrimaryKeyIndex(pIdx->pTable); assert(pk); int nPkCol = index_column_count(pk); - if (nPkCol == 1 - && pIdx->pTable->aCol[pk->aiColumn[0]].affinity == 'D') { + char affinity = + pIdx->pTable->def->fields[pk->aiColumn[0]].affinity; + if (nPkCol == 1 && affinity == 'D') { /* Right now INTEGER PRIMARY KEY is the only option to * get Tarantool's INTEGER column type. Need special handling * here: try to loosely convert FLOAT to INT. If RHS type @@ -1725,7 +1729,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t for (iPk = 0; iPk < nPk; iPk++) { int iCol = pPk->aiColumn[iPk]; sqlite3ExprCodeGetColumnToReg - (pParse, pTab, + (pParse, pTab->def, iCol, iCur, r + iPk); } diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c index e602111..d1f2cc5 100644 --- a/src/box/sql/whereexpr.c +++ b/src/box/sql/whereexpr.c @@ -1516,7 +1516,7 @@ sqlite3WhereTabFuncArgs(Parse * pParse, /* Parsing context */ return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - pColRef->pTab = pTab; + pColRef->space_def = pTab->def; pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); -- 2.7.4