[tarantool-patches] [PATCH] sql: add index_def to struct Index
Ivan Koptelov
ivan.koptelov at tarantool.org
Tue May 22 19:03:20 MSK 2018
Currently there is a problem with
non-deterministic nullability in
index_def. To see the error just
uncomment printfs on build.c 2999
and run any sql-tap test that
has to do with indexes, e.g
distinct.test.lua.
github branch: https://github.com/tarantool/tarantool/tree/sb/gh-3369-use-index-def-in-select-and-where
---
src/box/sql/build.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++-
src/box/sql/sqliteInt.h | 2 +
2 files changed, 179 insertions(+), 2 deletions(-)
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 742f8a572..6bd70fa9f 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -43,6 +43,7 @@
* COMMIT
* ROLLBACK
*/
+#include <ctype.h>
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "tarantoolInt.h"
@@ -2841,9 +2842,173 @@ index_is_unique(Index *idx)
return tnt_index->def->opts.is_unique;
}
+/*
+ * In CREATE INDEX requests user may set binary collation with COLLATE
+ * [BINARY, binary, "binary" and "bInarY"] This function is to handle all
+ * these cases.
+ */
+bool is_binary_collation(const char *coll_name)
+{
+ char *upper_case_name =
+ malloc(sizeof(*coll_name) * strlen(coll_name));
+ for (int i = 0; i < (int) strlen(coll_name); i++) {
+ upper_case_name[i] = toupper(coll_name[i]);
+ }
+
+ bool res = (strcmp(upper_case_name, "BINARY") == 0);
+ free(upper_case_name);
+ return res;
+}
+
+//bool is_index_equal(Index * old, struct index_def *new)
+//{
+// assert(strcmp(old->zName, new->name);
+// return true;
+//}
+
+struct index_def *create_index_def(Table *pTab, const char *name,
+ uint32_t name_len, int onError,
+ ExprList *pList, u8 idxType)
+{
+ struct space_def *space_def = pTab->def;
+ struct space *space = space_by_id(space_def->id);
+
+ uint32_t iid = 0;
+ Index *temp = pTab->pIndex;
+ while (temp != NULL) {
+ iid++;
+ temp = temp->pNext;
+ }
+
+ struct index_opts *opts = (struct index_opts *) malloc(sizeof(*opts));
+ index_opts_create(opts);
+ opts->sql = NULL;
+
+ if (onError == ON_CONFLICT_ACTION_NONE) {
+ opts->is_unique = false;
+ } else {
+ opts->is_unique = true;
+ }
+
+ struct key_part_def *part_def_tmp = (struct key_part_def *)
+ malloc(sizeof(*part_def_tmp) * pList->nExpr);
+
+ uint32_t part_count = 0;
+ int i = 0;
+ struct ExprList_item *pListItem;
+
+ /*
+ * In case of ordinary index creation we want ot store a
+ * SQL statement of this creation.
+ */
+ if (idxType == SQLITE_IDXTYPE_APPDEF) {
+ asprintf(&opts->sql,"CREATE INDEX %s ON %s(",
+ name, space_def->name);
+ }
+
+ for (i = 0, pListItem = pList->a; i < pList->nExpr; pListItem++, i++) {
+ Expr *pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr);
+
+ if (pCExpr->op == TK_COLUMN) {
+ uint32_t fieldno = pCExpr->iColumn;
+ part_def_tmp[i].fieldno = fieldno;
+ part_def_tmp[i].nullable_action =
+ ON_CONFLICT_ACTION_DEFAULT;
+ part_def_tmp[i].type =
+ space_def->fields[fieldno].type;
+
+// part_def_tmp[i].is_nullable =
+// (fieldno < space_def->field_count ?
+// space_def->fields[fieldno].is_nullable :
+// false);
+
+ part_def_tmp[i].is_nullable =
+ table_column_is_nullable(pTab->def, fieldno);
+
+ part_def_tmp[i].coll_id =
+ space_def->fields[fieldno].coll_id ?
+ space_def->fields[fieldno].coll_id : COLL_NONE;
+ part_count++;
+
+ if (opts->sql != NULL) {
+ if (part_count == 1) {
+ asprintf(&opts->sql,"%s%s,",opts->sql,
+ space_def->fields[fieldno].name);
+ } else {
+ asprintf(&opts->sql,"%s %s,",opts->sql,
+ space_def->fields[fieldno].name);
+ }
+ }
+ } else {
+ assert(pCExpr->op == TK_COLUMN);
+ }
+
+ if (pListItem->pExpr->op == TK_COLLATE) {
+ const char *coll_name = pListItem->pExpr->u.zToken;
+ assert(coll_name != NULL);
+ size_t coll_name_len = strlen(coll_name);
+ struct coll *coll = coll_by_name(coll_name, coll_name_len);
+
+ if (is_binary_collation(coll_name)) {
+ part_def_tmp[i].coll_id = COLL_NONE;
+ } else {
+ assert(coll != NULL);
+ part_def_tmp[i].coll_id = coll->id;
+ }
+
+ if (opts->sql != NULL) {
+ /*
+ * If index part has a collation then
+ * corresponding part of statement should
+ * be changed from 'column_name,' to
+ * 'column_name COLLATE collation_name,'.
+ */
+ opts->sql[strlen(opts->sql) - 1] = ' ';
+ asprintf(&opts->sql,"%sCOLLATE %s,", opts->sql,
+ coll_name);
+ }
+ }
+ if (pListItem->pExpr->op != TK_COLUMN &&
+ pListItem->pExpr->op != TK_COLLATE) {
+ printf("error %d\n", pListItem->pExpr->op);
+ }
+ }
+
+ if (idxType == SQLITE_IDXTYPE_APPDEF) {
+ opts->sql[strlen(opts->sql) - 1] = ')';
+ }
+
+ struct key_part_def *part_def = (struct key_part_def *)
+ malloc(sizeof(*part_def) * part_count + 1);
+
+ memcpy(part_def, part_def_tmp, sizeof(*part_def) * part_count);
+ free(part_def_tmp);
+
+ struct key_def *key_def = key_def_new_with_parts(part_def, part_count);
+ assert(key_def != NULL);
+
+ struct key_def *pk_key_def;
+ if (idxType == SQLITE_IDXTYPE_APPDEF) {
+ pk_key_def = space_index_key_def(space, 0);
+ } else {
+ pk_key_def = NULL;
+ }
+
+ enum index_type default_type = TREE;
+
+ printf("space id %d index name %s index iid %d\n", space_def->id, name, iid);
+ printf("nullables\n");
+ for (uint32_t j = 0; j < key_def->part_count; j++){
+ printf("%d\n", key_part_is_nullable(&key_def->parts[i]));
+ }
+
+ return index_def_new(space_def->id, iid, name, name_len,
+ default_type, opts, key_def, pk_key_def);
+}
+
/*
* Create a new index for an SQL table. pName1.pName2 is the name of the index
- * and pTblList is the name of the table that is to be indexed. Both will
+ * and pTblName is the name of the table that is to be indexed. Both will
* be NULL for a primary key or an index that is created to satisfy a
* UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable
* as the table to be indexed. pParse->pNewTable is a table that is
@@ -3187,6 +3352,13 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
/* Link the new Index structure to its table and to the other
* in-memory database structures.
*/
+
+ if (pIndex->def == NULL) {
+ pIndex->def =
+ create_index_def(pTab, zName, nName, onError,
+ pList, idxType);
+ }
+
assert(pParse->nErr == 0);
if (db->init.busy) {
Index *p;
@@ -3283,8 +3455,11 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
/* Clean up before exiting */
exit_create_index:
- if (pIndex)
+ if (pIndex) {
+ if (pIndex->def)
+ index_def_delete(pIndex->def);
freeIndex(db, pIndex);
+ }
sql_expr_free(db, pPIWhere, false);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 4c2c6fb69..b24abcf2b 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2151,6 +2151,8 @@ struct Index {
IndexSample *aSample; /* Samples of the left-most key */
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
+ /** Index definition with Tarantool metadata. */
+ struct index_def *def;
};
/*
--
2.14.3 (Apple Git-98)
More information about the Tarantool-patches
mailing list