diff --git a/src/box/sql.c b/src/box/sql.c index 7918f8a05bb62936092fced722c2e959430d170a..dc778a1c994db254b9fc8b15d4f3c304409c8b19 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -1663,6 +1663,11 @@ sql_index_id_by_token(const struct space *space, const struct Token *name) char *name_str = sql_name_from_token(name); uint32_t res = sql_space_index_id(space, name_str); sql_xfree(name_str); + if (res != UINT32_MAX || name->z[0] == '"') + return res; + char *old_name_str = sql_legacy_name_new(name->z, name->n); + res = sql_space_index_id(space, old_name_str); + sql_xfree(old_name_str); return res; } @@ -1670,7 +1675,10 @@ uint32_t sql_index_id_by_src(const struct SrcList_item *src) { assert(src->space != NULL && src->fg.isIndexedBy != 0); - return sql_space_index_id(src->space, src->u1.zIndexedBy); + uint32_t res = sql_space_index_id(src->space, src->u1.zIndexedBy); + if (res != UINT32_MAX || src->legacy_index_name == NULL) + return res; + return sql_space_index_id(src->space, src->legacy_index_name); } uint32_t diff --git a/src/box/sql/build.c b/src/box/sql/build.c index bd5de51a58d1d151471f220270af1c0779796d10..2b93b7bcc43081e833aaba2b18f1ed3fcd472a35 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -3055,8 +3055,10 @@ sqlSrcListDelete(struct SrcList *pList) sql_xfree(pItem->zName); sql_xfree(pItem->zAlias); sql_xfree(pItem->legacy_name); - if (pItem->fg.isIndexedBy) + if (pItem->fg.isIndexedBy) { sql_xfree(pItem->u1.zIndexedBy); + sql_xfree(pItem->legacy_index_name); + } if (pItem->fg.isTabFunc) sql_expr_list_delete(pItem->u1.pFuncArg); /* @@ -3132,6 +3134,11 @@ sqlSrcListIndexedBy(struct SrcList *p, struct Token *pIndexedBy) } else if (pIndexedBy->z != NULL) { pItem->u1.zIndexedBy = sql_name_from_token(pIndexedBy); pItem->fg.isIndexedBy = true; + if (pIndexedBy->z[0] != '"') { + pItem->legacy_index_name = + sql_legacy_name_new(pIndexedBy->z, + pIndexedBy->n); + } } } } diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 604bf4a728b651b4ef62c8b959a200220c95c444..c174c70a60a3587b1ceae493bb42885f9b44836a 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -1668,6 +1668,8 @@ sqlSrcListDup(struct SrcList *p, int flags) if (pNewItem->fg.isIndexedBy) { pNewItem->u1.zIndexedBy = sql_xstrdup(pOldItem->u1.zIndexedBy); + pNewItem->legacy_index_name = + sql_xstrdup(pOldItem->legacy_index_name); } pNewItem->pIBIndex = pOldItem->pIBIndex; if (pNewItem->fg.isTabFunc) { diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 6def8ed3196af3c59ca37dc4d4ad42a9aa3ed861..babb716f81cbc33f515796a1cef5dae5b0b061ed 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -1630,6 +1630,8 @@ struct SrcList { char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */ ExprList *pFuncArg; /* Arguments to table-valued-function */ } u1; + /** Normalized index name for the second lookup. */ + char *legacy_index_name; struct index_def *pIBIndex; } a[1]; /* One entry for each identifier on the list */ }; @@ -3120,15 +3122,18 @@ uint32_t sql_space_fieldno(const struct space *space, const char *name); /** - * Return id of index with the name defined by the token. Return UINT32_MAX if - * the index was not found. + * Return id of index with the name defined by the token. A second lookup will + * be performed if the index is not found on the first try and token is not + * start with double quote. Return UINT32_MAX if the index was not found. */ uint32_t sql_index_id_by_token(const struct space *space, const struct Token *name); /** - * Return index with name defined by the element of struct SrcList. Return NULL - * if the index was not found. + * Return index with name defined by the element of struct SrcList. A second + * lookup will be performed if the index is not found on the first try and field + * legacy_index_name of the src is not NULL. Return NULL if the index was not + * found. */ uint32_t sql_index_id_by_src(const struct SrcList_item *src); diff --git a/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua b/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua index e2759e64624e7944437ae81d3e77fd2b8d21a305..e0135065c71d1886588acdce69669598a8e68416 100644 --- a/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua +++ b/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua @@ -274,6 +274,13 @@ g.test_indexed_by = function() local _, err = box.execute([[SELECT * FROM Tab INDEXED BY Four;]]) t.assert(err == nil); box.space.Tab:drop() + + -- Make sure index name is looked up twice in INDEXED BY clause. + box.execute([[CREATE TABLE ASD(QWE INT PRIMARY KEY, ZXC INT, + CONSTRAINT RTY UNIQUE (qwe, zxc));]]) + _, err = box.execute([[SELECT * FROM asd INDEXED BY rty;]]) + t.assert(err == nil); + box.space.ASD:drop() end) end @@ -390,11 +397,12 @@ g.test_drop_index = function() t.assert(box.space.Tab.index.In1 == nil) box.space.Tab:drop() - -- Make sure table name is looked up twice in DROP INDEX. + -- Make sure table name and index name are looked up twice in + -- DROP INDEX. box.execute([[CREATE TABLE ASD(PK INT PRIMARY KEY, QWE INT, ZXC INT);]]) box.execute([[CREATE INDEX IND ON aSd(ZXC, QWE);]]) t.assert(box.space.ASD.index.IND ~= nil) - sql = [[DROP INDEX IND ON asD;]] + sql = [[DROP INDEX iNd ON asD;]] t.assert_equals(box.execute(sql), {row_count = 1}) t.assert(box.space.ASD.index.IND == nil) box.space.ASD:drop() @@ -411,12 +419,12 @@ g.test_pragma = function() t.assert_equals(box.execute([[PRAGMA index_info(Tab.In1);]]).rows, exp) box.space.Tab:drop() - -- Make sure table name is looked up twice in PRAGMA. + -- Make sure table name and index name are looked up twice in PRAGMA. box.execute([[CREATE TABLE ASD(PK INT PRIMARY KEY, QWE INT, ZXC INT);]]) box.execute([[CREATE INDEX IND ON asD(ZXC, QWE);]]) local exp = {{0, 2, 'ZXC', 0, 'BINARY', 'integer'}, {1, 1, 'QWE', 0, 'BINARY', 'integer'}} - t.assert_equals(box.execute([[PRAGMA index_info(aSD.IND);]]).rows, exp) + t.assert_equals(box.execute([[PRAGMA index_info(aSD.inD);]]).rows, exp) box.space.ASD:drop() end) end