[tarantool-patches] Re: [PATCH 1/2] sql: introduce sort order to key_part/key_part_def
Kirill Yukhin
kyukhin at tarantool.org
Thu May 10 16:01:22 MSK 2018
Hello Vlad,
Thanks for review. Updated patch in the bottom.
On 08 мая 19:02, Vladislav Shpilevoy wrote:
> Hello. Thanks for contributing! See 2 comments below.
>
> 1. I still can grep SQLITE_SO_ASC/DESC in build.c
Fixed.
>
> On 08/05/2018 10:56, Kirill Yukhin wrote:
> > Legacy SQL DD structs contained sort_order, defined per
> > index column. During integration, those structs are to be
> > vanished. So, introduce new field to part entity of Tarantool.
> > This field states for sorting order of given part in give index.
> > This field is ignored by Tarantool everywhere excpept for
> > some of nested queries in SQL.
> >
> > Patch also replaces usages of SQL's stored sort order w/ this new
> > field.
> >
> > Part of #3235
> > ---
> > src/box/key_def.cc | 28 ++++++++++++++++++++++------
> > src/box/key_def.h | 16 +++++++++++++++-
> > src/box/schema.cc | 30 ++++++++++++++++++++----------
> > src/box/sql.c | 11 +++++++++--
> > src/box/sql/build.c | 47 ++++++++++++++++++++++++++++++++++++-----------
> > src/box/sql/expr.c | 9 ++++-----
> > src/box/sql/insert.c | 3 ++-
> > src/box/sql/parse.y | 10 +++++-----
> > src/box/sql/pragma.c | 7 ++++---
> > src/box/sql/select.c | 2 +-
> > src/box/sql/sqliteInt.h | 20 ++++++++++++--------
> > src/box/sql/vdbe.h | 1 +
> > src/box/sql/where.c | 11 ++++++-----
> > src/box/sql/wherecode.c | 10 ++++++----
> > 14 files changed, 143 insertions(+), 62 deletions(-)
> >
> > diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
> > index 8bb45c9..a811932 100644
> > --- a/src/box/sql/sqliteInt.h
> > +++ b/src/box/sql/sqliteInt.h
> > @@ -3540,6 +3534,16 @@ sql_default_coll();
> > bool
> > space_is_view(Table *);
> > +/**
> > + * Return name of given column collation from index.
>
> 2. Irrelevant comment.
Fixed.
--
Regards, Kirill Yukhin
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 98719c2..9f1a373 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -36,12 +36,15 @@
#include "schema_def.h"
#include "coll_cache.h"
+const char *sort_order_strs[] = { "asc", "desc", "undef" };
+
static const struct key_part_def key_part_def_default = {
0,
field_type_MAX,
COLL_NONE,
false,
- ON_CONFLICT_ACTION_ABORT
+ ON_CONFLICT_ACTION_ABORT,
+ SORT_ORDER_ASC
};
static int64_t
@@ -55,6 +58,7 @@ part_type_by_name_wrapper(const char *str, uint32_t len)
#define PART_OPT_COLLATION "collation"
#define PART_OPT_NULLABILITY "is_nullable"
#define PART_OPT_NULLABLE_ACTION "nullable_action"
+#define PART_OPT_SORT_ORDER "sort_order"
const struct opt_def part_def_reg[] = {
OPT_DEF_ENUM(PART_OPT_TYPE, field_type, struct key_part_def, type,
@@ -65,6 +69,8 @@ const struct opt_def part_def_reg[] = {
is_nullable),
OPT_DEF_ENUM(PART_OPT_NULLABLE_ACTION, on_conflict_action,
struct key_part_def, nullable_action, NULL),
+ OPT_DEF_ENUM(PART_OPT_SORT_ORDER, sort_order, struct key_part_def,
+ sort_order, NULL),
OPT_END,
};
@@ -169,7 +175,7 @@ key_def_new_with_parts(struct key_part_def *parts, uint32_t part_count)
}
}
key_def_set_part(def, i, part->fieldno, part->type,
- part->nullable_action, coll);
+ part->nullable_action, coll, part->sort_order);
}
return def;
}
@@ -199,7 +205,8 @@ box_key_def_new(uint32_t *fields, uint32_t *types, uint32_t part_count)
for (uint32_t item = 0; item < part_count; ++item) {
key_def_set_part(key_def, item, fields[item],
(enum field_type)types[item],
- key_part_def_default.nullable_action, NULL);
+ key_part_def_default.nullable_action,
+ NULL, SORT_ORDER_ASC);
}
return key_def;
}
@@ -252,7 +259,7 @@ key_part_cmp(const struct key_part *parts1, uint32_t part_count1,
void
key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
enum field_type type, enum on_conflict_action nullable_action,
- struct coll *coll)
+ struct coll *coll, enum sort_order sort_order)
{
assert(part_no < def->part_count);
assert(type < field_type_MAX);
@@ -261,6 +268,7 @@ key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
def->parts[part_no].fieldno = fieldno;
def->parts[part_no].type = type;
def->parts[part_no].coll = coll;
+ def->parts[part_no].sort_order = sort_order;
column_mask_set_fieldno(&def->column_mask, fieldno);
/**
* When all parts are set, initialize the tuple
@@ -510,6 +518,12 @@ key_def_decode_parts(struct key_part_def *parts, uint32_t part_count,
"nullable action properties");
return -1;
}
+ if (part->sort_order == sort_order_MAX) {
+ diag_set(ClientError, ER_WRONG_INDEX_OPTIONS,
+ i + TUPLE_INDEX_BASE,
+ "index part: unknown sort order");
+ return -1;
+ }
}
return 0;
}
@@ -572,7 +586,8 @@ key_def_merge(const struct key_def *first, const struct key_def *second)
end = part + first->part_count;
for (; part != end; part++) {
key_def_set_part(new_def, pos++, part->fieldno, part->type,
- part->nullable_action, part->coll);
+ part->nullable_action, part->coll,
+ part->sort_order);
}
/* Set-append second key def's part to the new key def. */
@@ -582,7 +597,8 @@ key_def_merge(const struct key_def *first, const struct key_def *second)
if (key_def_find(first, part->fieldno))
continue;
key_def_set_part(new_def, pos++, part->fieldno, part->type,
- part->nullable_action, part->coll);
+ part->nullable_action, part->coll,
+ part->sort_order);
}
return new_def;
}
diff --git a/src/box/key_def.h b/src/box/key_def.h
index a02bfa1..4b18175 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -45,6 +45,16 @@ extern "C" {
/* MsgPack type names */
extern const char *mp_type_strs[];
+/* Sorting order of a part. */
+extern const char *sort_order_strs[];
+
+enum sort_order {
+ SORT_ORDER_ASC = 0,
+ SORT_ORDER_DESC,
+ SORT_ORDER_UNDEF,
+ sort_order_MAX
+};
+
struct key_part_def {
/** Tuple field index for this part. */
uint32_t fieldno;
@@ -56,6 +66,8 @@ struct key_part_def {
bool is_nullable;
/** Action to perform if NULL constraint failed. */
enum on_conflict_action nullable_action;
+ /** Part sort order. */
+ enum sort_order sort_order;
};
/**
@@ -74,6 +86,8 @@ struct key_part {
struct coll *coll;
/** Action to perform if NULL constraint failed. */
enum on_conflict_action nullable_action;
+ /** Part sort order. */
+ enum sort_order sort_order;
};
struct key_def;
@@ -264,7 +278,7 @@ key_def_dump_parts(const struct key_def *def, struct key_part_def *parts);
void
key_def_set_part(struct key_def *def, uint32_t part_no, uint32_t fieldno,
enum field_type type, enum on_conflict_action nullable_action,
- struct coll *coll);
+ struct coll *coll, enum sort_order sort_order);
/**
* Update 'has_optional_parts' of @a key_def with correspondence
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 2e14ec2..c3a8f93 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -279,13 +279,15 @@ schema_init()
auto key_def_guard = make_scoped_guard([&] { key_def_delete(key_def); });
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
sc_space_new(BOX_SCHEMA_ID, "_schema", key_def, &on_replace_schema,
NULL);
/* _space - home for all spaces. */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* _collation - collation description. */
sc_space_new(BOX_COLLATION_ID, "_collation", key_def,
@@ -329,7 +331,8 @@ schema_init()
/* _trigger - all existing SQL triggers. */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
sc_space_new(BOX_TRIGGER_ID, "_trigger", key_def, &on_replace_trigger, NULL);
key_def_delete(key_def);
@@ -338,19 +341,23 @@ schema_init()
diag_raise();
/* space no */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* index no */
key_def_set_part(key_def, 1 /* part no */, 1 /* field no */,
- FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_UNSIGNED, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
sc_space_new(BOX_INDEX_ID, "_index", key_def,
&alter_space_on_replace_index, &on_stmt_begin_index);
/* space name */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* index name */
key_def_set_part(key_def, 1 /* part no */, 1 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* _sql_stat1 - a simpler statistics on space, seen in SQL. */
sc_space_new(BOX_SQL_STAT1_ID, "_sql_stat1", key_def, NULL, NULL);
@@ -361,13 +368,16 @@ schema_init()
/* space name */
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* index name */
key_def_set_part(key_def, 1 /* part no */, 1 /* field no */,
- FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_STRING, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* sample */
key_def_set_part(key_def, 2 /* part no */, 5 /* field no */,
- FIELD_TYPE_SCALAR, ON_CONFLICT_ACTION_ABORT, NULL);
+ FIELD_TYPE_SCALAR, ON_CONFLICT_ACTION_ABORT, NULL,
+ SORT_ORDER_ASC);
/* _sql_stat4 - extensive statistics on space, seen in SQL. */
sc_space_new(BOX_SQL_STAT4_ID, "_sql_stat4", key_def, NULL, NULL);
}
diff --git a/src/box/sql.c b/src/box/sql.c
index 166bb71..838fcf6 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -384,7 +384,8 @@ int tarantoolSqlite3EphemeralCreate(BtCursor *pCur, uint32_t field_count,
part /* filed no */,
FIELD_TYPE_SCALAR,
ON_CONFLICT_ACTION_NONE /* nullable_action */,
- aColl /* coll */);
+ aColl /* coll */,
+ SORT_ORDER_ASC);
}
struct index_def *ephemer_index_def =
@@ -1555,7 +1556,7 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
else
t = convertSqliteAffinity(aCol[col].affinity, aCol[col].notNull == 0);
/* do not decode default collation */
- p = enc->encode_map(p, pIndex->coll_array[i] == NULL ? 4 : 5);
+ p = enc->encode_map(p, pIndex->coll_array[i] == NULL ? 5 : 6);
p = enc->encode_str(p, "type", sizeof("type")-1);
p = enc->encode_str(p, t, strlen(t));
p = enc->encode_str(p, "field", sizeof("field")-1);
@@ -1569,6 +1570,12 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
p = enc->encode_str(p, "nullable_action", 15);
const char *action_str = on_conflict_action_strs[aCol[col].notNull];
p = enc->encode_str(p, action_str, strlen(action_str));
+
+ p = enc->encode_str(p, "sort_order", 10);
+ enum sort_order sort_order = pIndex->sort_order[i];
+ assert(sort_order < sort_order_MAX);
+ const char *sort_order_str = sort_order_strs[sort_order];
+ p = enc->encode_str(p, sort_order_str, strlen(sort_order_str));
}
return (int)(p - base);
}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index a2b712a..029c71e 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -930,7 +930,7 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
ExprList * pList, /* List of field names to be indexed */
int onError, /* What to do with a uniqueness conflict */
int autoInc, /* True if the AUTOINCREMENT keyword is present */
- int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
+ enum sort_order sortOrder
)
{
Table *pTab = pParse->pNewTable;
@@ -976,7 +976,7 @@ sqlite3AddPrimaryKey(Parse * pParse, /* Parsing context */
if (nTerm == 1
&& pCol
&& (sqlite3ColumnType(pCol) == FIELD_TYPE_INTEGER)
- && sortOrder != SQLITE_SO_DESC) {
+ && sortOrder != SORT_ORDER_DESC) {
assert(autoInc == 0 || autoInc == 1);
pTab->iPKey = iCol;
pTab->keyConf = (u8) onError;
@@ -1125,6 +1125,30 @@ sql_index_collation(Index *idx, uint32_t column)
return index->def->key_def->parts[column].coll;
}
+enum sort_order
+sql_index_column_sort_order(Index *idx, uint32_t column)
+{
+ assert(idx != NULL);
+ uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(idx->pTable->tnum);
+ struct space *space = space_by_id(space_id);
+
+ assert(column < idx->nColumn);
+ /*
+ * If space is still under construction, or it is
+ * an ephemeral space, then fetch collation from
+ * SQL internal structure.
+ */
+ if (space == NULL) {
+ assert(column < idx->nColumn);
+ return idx->sort_order[column];
+ }
+
+ uint32_t index_id = SQLITE_PAGENO_TO_INDEXID(idx->tnum);
+ struct index *index = space_index(space, index_id);
+ assert(index != NULL && index->def->key_def->part_count >= column);
+ return index->def->key_def->parts[column].sort_order;
+}
+
/**
* Return true if space which corresponds to
* given table has view option.
@@ -2694,11 +2718,11 @@ sqlite3AllocateIndexObject(sqlite3 * db, /* Database connection */
Index *p; /* Allocated index object */
int nByte; /* Bytes of space for Index object + arrays */
- nByte = ROUND8(sizeof(Index)) + /* Index structure */
- ROUND8(sizeof(char *) * nCol) + /* Index.azColl */
- ROUND8(sizeof(LogEst) * (nCol + 1) + /* Index.aiRowLogEst */
- sizeof(i16) * nCol + /* Index.aiColumn */
- sizeof(u8) * nCol); /* Index.aSortOrder */
+ nByte = ROUND8(sizeof(Index)) + /* Index structure */
+ ROUND8(sizeof(char *) * nCol) + /* Index.azColl */
+ ROUND8(sizeof(LogEst) * (nCol + 1) + /* Index.aiRowLogEst */
+ sizeof(i16) * nCol + /* Index.aiColumn */
+ sizeof(enum sort_order) * nCol); /* Index.sort_order */
p = sqlite3DbMallocZero(db, nByte + nExtra);
if (p) {
char *pExtra = ((char *)p) + ROUND8(sizeof(Index));
@@ -2708,7 +2732,7 @@ sqlite3AllocateIndexObject(sqlite3 * db, /* Database connection */
pExtra += sizeof(LogEst) * (nCol + 1);
p->aiColumn = (i16 *) pExtra;
pExtra += sizeof(i16) * nCol;
- p->aSortOrder = (u8 *) pExtra;
+ p->sort_order = (enum sort_order *) pExtra;
p->nColumn = nCol;
*ppExtra = ((char *)p) + nByte;
}
@@ -3037,7 +3061,7 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
*/
for (i = 0, pListItem = pList->a; i < pList->nExpr; i++, pListItem++) {
Expr *pCExpr; /* The i-th index expression */
- int requestedSortOrder; /* ASC or DESC on the i-th expression */
+ enum sort_order requested_so; /* ASC or DESC on the i-th expression */
sqlite3ResolveSelfReference(pParse, pTab, NC_IdxExpr,
pListItem->pExpr, 0);
if (pParse->nErr)
@@ -3075,8 +3099,8 @@ sqlite3CreateIndex(Parse * pParse, /* All information about this parse */
/* Tarantool: DESC indexes are not supported so far.
* See gh-3016.
*/
- requestedSortOrder = pListItem->sortOrder & 0;
- pIndex->aSortOrder[i] = (u8) requestedSortOrder;
+ requested_so = pListItem->sortOrder & 0;
+ pIndex->sort_order[i] = requested_so;
}
sqlite3DefaultRowEst(pIndex);
@@ -4199,7 +4223,8 @@ sqlite3KeyInfoOfIndex(Parse * pParse, sqlite3 * db, Index * pIdx)
assert(sqlite3KeyInfoIsWriteable(pKey));
for (i = 0; i < nCol; i++) {
pKey->aColl[i] = sql_index_collation(pIdx, i);
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+ pKey->aSortOrder[i] = sql_index_column_sort_order(pIdx,
+ i);
}
if (pParse && pParse->nErr) {
sqlite3KeyInfoUnref(pKey);
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 0c86761..cc969ca 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -1764,11 +1764,9 @@ sqlite3ExprListSetSortOrder(ExprList * p, int iSortOrder)
{
if (p == 0)
return;
- assert(SQLITE_SO_UNDEFINED < 0 && SQLITE_SO_ASC >= 0
- && SQLITE_SO_DESC > 0);
assert(p->nExpr > 0);
- if (iSortOrder < 0) {
- assert(p->a[p->nExpr - 1].sortOrder == SQLITE_SO_ASC);
+ if (iSortOrder == SORT_ORDER_UNDEF) {
+ assert(p->a[p->nExpr - 1].sortOrder == SORT_ORDER_ASC);
return;
}
p->a[p->nExpr - 1].sortOrder = (u8) iSortOrder;
@@ -2529,7 +2527,8 @@ sqlite3FindInIndex(Parse * pParse, /* Parsing context */
assert(IN_INDEX_INDEX_DESC ==
IN_INDEX_INDEX_ASC + 1);
eType = IN_INDEX_INDEX_ASC +
- pIdx->aSortOrder[0];
+ sql_index_column_sort_order(pIdx,
+ 0);
if (prRhsHasNull) {
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 939b5e3..1a34f71 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1653,7 +1653,8 @@ xferCompatibleIndex(Index * pDest, Index * pSrc)
return 0; /* Different expressions in the index */
}
}
- if (pSrc->aSortOrder[i] != pDest->aSortOrder[i]) {
+ if (sql_index_column_sort_order(pSrc, i) !=
+ sql_index_column_sort_order(pDest, i)) {
return 0; /* Different sort orders */
}
if (sql_index_collation(pSrc, i) !=
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index b078e20..249d20d 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -684,9 +684,9 @@ sortlist(A) ::= expr(Y) sortorder(Z). {
%type sortorder {int}
-sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;}
-sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;}
-sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;}
+sortorder(A) ::= ASC. {A = SORT_ORDER_ASC;}
+sortorder(A) ::= DESC. {A = SORT_ORDER_DESC;}
+sortorder(A) ::= . {A = SORT_ORDER_UNDEF;}
%type groupby_opt {ExprList*}
%destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);}
@@ -1244,7 +1244,7 @@ cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X)
ON nm(Y) LP sortlist(Z) RP where_opt(W). {
sqlite3CreateIndex(pParse, &X,
sqlite3SrcListAppend(pParse->db,0,&Y), Z, U,
- &S, W, SQLITE_SO_ASC, NE, SQLITE_IDXTYPE_APPDEF);
+ &S, W, SORT_ORDER_ASC, NE, SQLITE_IDXTYPE_APPDEF);
}
%type uniqueflag {int}
@@ -1279,7 +1279,7 @@ uniqueflag(A) ::= . {A = ON_CONFLICT_ACTION_NONE;}
int sortOrder
){
ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0);
- if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED)
+ if( (hasCollate || sortOrder != SORT_ORDER_UNDEF)
&& pParse->db->init.busy==0
){
sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"",
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index e41f69b..738c254 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -463,12 +463,13 @@ sqlite3Pragma(Parse * pParse, Token * pId, /* First part of [schema.]id field */
c_n = coll->name;
else
c_n = "BINARY";
+ enum sort_order sort_order;
+ sort_order = sql_index_column_sort_order(pIdx,
+ i);
sqlite3VdbeMultiLoad(v,
4,
"isi",
- pIdx->
- aSortOrder
- [i],
+ sort_order,
c_n,
i <
mx);
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 5a50413..aff534d3 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -5620,7 +5620,7 @@ sqlite3Select(Parse * pParse, /* The parser context */
* and plus one column for ID.
*/
int nCols = pEList->nExpr + sSort.pOrderBy->nExpr + 1;
- if (pKeyInfo->aSortOrder[0] == SQLITE_SO_DESC) {
+ if (pKeyInfo->aSortOrder[0] == SORT_ORDER_DESC) {
sSort.sortFlags |= SORTFLAG_DESC;
}
sSort.addrSortIndex =
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 8bb45c9..c2c1090 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1881,13 +1881,6 @@ struct Column {
u8 is_primkey; /* Boolean propertie for being PK */
};
-/*
- * A sort order can be either ASC or DESC.
- */
-#define SQLITE_SO_ASC 0 /* Sort in ascending order */
-#define SQLITE_SO_DESC 1 /* Sort in ascending order */
-#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
-
/*
* Column affinity types.
*
@@ -2143,7 +2136,8 @@ struct Index {
char *zColAff; /* String defining the affinity of each column */
Index *pNext; /* The next index associated with the same table */
Schema *pSchema; /* Schema containing this index */
- u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
+ /** Sorting order for each column. */
+ enum sort_order *sort_order;
/** Array of collation sequences for index. */
struct coll **coll_array;
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
@@ -3522,7 +3516,7 @@ Index *sqlite3PrimaryKeyIndex(Table *);
void sqlite3StartTable(Parse *, Token *, int);
void sqlite3AddColumn(Parse *, Token *, Token *);
void sqlite3AddNotNull(Parse *, int);
-void sqlite3AddPrimaryKey(Parse *, ExprList *, int, int, int);
+void sqlite3AddPrimaryKey(Parse *, ExprList *, int, int, enum sort_order);
void sqlite3AddCheckConstraint(Parse *, Expr *);
void sqlite3AddDefaultValue(Parse *, ExprSpan *);
void sqlite3AddCollateType(Parse *, Token *);
@@ -3540,6 +3534,16 @@ sql_default_coll();
bool
space_is_view(Table *);
+/**
+ * Return sort order of given column from index.
+ *
+ * @param idx Index which is used to fetch column.
+ * @param column Number of column.
+ * @retval Sort order of requested column.
+ */
+enum sort_order
+sql_index_column_sort_order(Index *idx, uint32_t column);
+
void sqlite3EndTable(Parse *, Token *, Token *, Select *);
int
emit_open_cursor(Parse *, int, int);
diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
index 340ddc7..e244606 100644
--- a/src/box/sql/vdbe.h
+++ b/src/box/sql/vdbe.h
@@ -145,6 +145,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */
#define P4_BOOL (-17) /* P4 is a bool value */
#define P4_PTR (-18) /* P4 is a generic pointer */
+#define P4_KEYDEF (-19) /* P4 is a pointer to key_def structure. */
/* Error message codes for OP_Halt */
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 7a7103c..bad964a 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -1336,8 +1336,8 @@ whereRangeScanEst(Parse * pParse, /* Parsing & code generating context */
|| (pLower->eOperator & (WO_GT | WO_GE)) != 0);
assert(pUpper == 0
|| (pUpper->eOperator & (WO_LT | WO_LE)) != 0);
- assert(p->aSortOrder != 0);
- if (p->aSortOrder[nEq]) {
+ if (sql_index_column_sort_order(p, nEq) !=
+ SORT_ORDER_ASC) {
/* The roles of pLower and pUpper are swapped for a DESC index */
SWAP(pLower, pUpper);
SWAP(nBtm, nTop);
@@ -2229,8 +2229,8 @@ whereRangeVectorLen(Parse * pParse, /* Parsing context */
if (pLhs->op != TK_COLUMN
|| pLhs->iTable != iCur
|| pLhs->iColumn != pIdx->aiColumn[i + nEq]
- || pIdx->aSortOrder[i + nEq] != pIdx->aSortOrder[nEq]
- ) {
+ || sql_index_column_sort_order(pIdx, i + nEq) !=
+ sql_index_column_sort_order(pIdx, nEq)) {
break;
}
@@ -3316,7 +3316,8 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo, /* The WHERE clause */
*/
if (pIndex) {
iColumn = pIndex->aiColumn[j];
- revIdx = pIndex->aSortOrder[j];
+ revIdx = sql_index_column_sort_order(pIndex,
+ j);
if (iColumn == pIndex->pTable->iPKey)
iColumn = -1;
} else {
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index f1112f2..231d690 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -462,7 +462,8 @@ codeEqualityTerm(Parse * pParse, /* The parsing context */
int nEq = 0;
int *aiMap = 0;
- if (pLoop->pIndex != 0 && pLoop->pIndex->aSortOrder[iEq]) {
+ if (pLoop->pIndex != 0 &&
+ sql_index_column_sort_order(pLoop->pIndex, iEq)) {
testcase(iEq == 0);
testcase(bRev);
bRev = !bRev;
@@ -1296,12 +1297,12 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
*/
testcase(bRev);
testcase(pIdx->aSortOrder[nEq] ==
- SQLITE_SO_DESC);
+ SORT_ORDER_DESC);
assert((bRev & ~1) == 0);
pLevel->iLikeRepCntr <<= 1;
pLevel->iLikeRepCntr |=
- bRev ^ (pIdx->aSortOrder[nEq] ==
- SQLITE_SO_DESC);
+ bRev ^ (sql_index_column_sort_order(pIdx, nEq) ==
+ SORT_ORDER_DESC);
}
#endif
if (pRangeStart == 0) {
@@ -1320,7 +1321,8 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo, /* Complete information about t
* start and end terms (pRangeStart and pRangeEnd).
*/
if ((nEq < nIdxCol &&
- bRev == (pIdx->aSortOrder[nEq] == SQLITE_SO_ASC)) ||
+ bRev == (sql_index_column_sort_order(pIdx, nEq) ==
+ SORT_ORDER_ASC)) ||
(bRev && nIdxCol == nEq)) {
SWAP(pRangeEnd, pRangeStart);
SWAP(bSeekPastNull, bStopAtNull);
More information about the Tarantool-patches
mailing list