From: Nikita Pettik <korablev@tarantool.org> To: Mergen Imeev <imeevma@tarantool.org> Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH v1 1/1] sql: use rowid as PK of ephemeral space on INSERT Date: Wed, 11 Mar 2020 15:27:59 +0000 [thread overview] Message-ID: <20200311152759.GA29797@tarantool.org> (raw) In-Reply-To: <20200225101729.GA28823@tarantool.org> On 25 Feb 13:17, Mergen Imeev wrote: > Hi! Thank you for review. My answers and new patch beliw. > Date: Mon, 24 Feb 2020 16:44:07 +0300 > Subject: [PATCH] sql: do not change order of inserted values on INSERT > > Prior to this patch, if ephemeral space was used during INSERT, Does fix affect only insert, but not replace? Or both? > the inserted values were sorted by the first column. Are inserted values are always sorted during insertion op? > This can lead > to an error when using the autoincrement feature. Why? Could you please provide details? Not personally for me, but in commit message. > To avoid this, > the patch makes it possible to make the rowid of the value > inserted into the ephemeral space be the first part of > ephemeral space index. So, before patch rowid could be only last column of table? And you achieve it extending sql_key_info with additional field? All these tip-questions should help you to make commit message more informative. > Closes #4256 Please attach a changelog to the patch. > > diff --git a/src/box/sql.c b/src/box/sql.c > index 1256df8..47cf235 100644 > --- a/src/box/sql.c > +++ b/src/box/sql.c > @@ -338,7 +338,10 @@ sql_ephemeral_space_create(uint32_t field_count, struct sql_key_info *key_info) > return NULL; > } > for (uint32_t i = 0; i < field_count; ++i) { > - struct key_part_def *part = &ephemer_key_parts[i]; > + uint32_t j = i; > + if (key_info != NULL && key_info->is_rowid_first) > + j = (j + 1) % field_count; What is going on here?? > + struct key_part_def *part = &ephemer_key_parts[j]; > part->fieldno = i; > part->nullable_action = ON_CONFLICT_ACTION_NONE; > part->is_nullable = true; > diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c > index 43a0de5..6ee728a 100644 > --- a/src/box/sql/insert.c > +++ b/src/box/sql/insert.c > @@ -455,8 +455,17 @@ sqlInsert(Parse * pParse, /* Parser context */ > reg_eph = ++pParse->nMem; > regRec = sqlGetTempReg(pParse); > regCopy = sqlGetTempRange(pParse, nColumn + 1); > - sqlVdbeAddOp2(v, OP_OpenTEphemeral, reg_eph, > - nColumn + 1); > + /* > + * This key_info is used to show that > + * rowid should be the first part of PK. > + */ Please, explain here why rowid should come as first column. See reference example in sql_table_delete_from(): 233 if (is_view) { 234 /* 235 * At this stage SELECT is already materialized 236 * into ephemeral table, which has one additional 237 * tail field (except for ones specified in view 238 * format) which contains sequential ids. These ids 239 * are required since selected values may turn out to 240 * be non-unique. For instance: 241 * CREATE TABLE t (id INT PRIMARY KEY, a INT); 242 * INSERT INTO t VALUES (1, 1), (2, 1), (3, 1); 243 * CREATE VIEW v AS SELECT a FROM t; ... > + struct sql_key_info *key_info = > + sql_key_info_new(pParse->db, nColumn + 1); > + key_info->parts[nColumn].type = FIELD_TYPE_UNSIGNED; > + key_info->is_rowid_first = true; > + sqlVdbeAddOp4(v, OP_OpenTEphemeral, reg_eph, > + nColumn + 1, 0, (char *)key_info, > + P4_KEYINFO); > addrL = sqlVdbeAddOp1(v, OP_Yield, dest.iSDParm); > VdbeCoverage(v); > sqlVdbeAddOp2(v, OP_NextIdEphemeral, reg_eph, > diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h > index d1fcf47..d9da921 100644 > --- a/src/box/sql/sqlInt.h > +++ b/src/box/sql/sqlInt.h > @@ -4111,6 +4111,8 @@ struct sql_key_info { > struct key_def *key_def; > /** Reference counter. */ > uint32_t refs; > + /** Rowid should be the first part of PK if true. */ > + bool is_rowid_first; Otherwise it is last or not presented at all? > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c > index 620d74e..db782a7 100644 > --- a/src/box/sql/vdbe.c > +++ b/src/box/sql/vdbe.c > @@ -2702,8 +2702,25 @@ case OP_Column: { > * key parts. > */ > if (pC->uc.pCursor->curFlags & BTCF_TEphemCursor) { > - field_type = pC->uc.pCursor->index->def-> > - key_def->parts[p2].type; > + struct key_def *key_def = > + pC->uc.pCursor->index->def->key_def; > + /* > + * There are three options: > + * |Rowid|First field|...|Last field| > + * Or: > + * |First field|...|Last field| > + * Or: > + * |First field|...|Last field|Rowid| > + * > + * If ephemeral space has a rowid column, But it contradicts schema above. > + * it is always the last column. Due to > + * this, the field number of the rowid > + * column cannot be 0. > + */ > + int partno = p2; > + if (key_def->parts[0].fieldno != 0) > + partno = (partno + 1) % key_def->part_count; See this for the second time, still don't understand what it is supposed to mean. > + field_type = key_def->parts[partno].type; > } else if (pC->uc.pCursor->curFlags & BTCF_TaCursor) { > field_type = pC->uc.pCursor->space->def-> > fields[p2].type; > diff --git a/test/sql/autoincrement.test.lua b/test/sql/autoincrement.test.lua > index 63a902a..99f4813 100644 > --- a/test/sql/autoincrement.test.lua > +++ b/test/sql/autoincrement.test.lua > @@ -31,3 +31,13 @@ seqs = box.space._sequence:select{} > #seqs == 0 or seqs > > box.schema.user.drop('user1') > + > +-- > +-- gh-4256: make sure that when inserting, values are inserted in > +-- the given order when ephemeral space is used. > +-- > +box.execute('CREATE TABLE t (i INT PRIMARY KEY AUTOINCREMENT);') > +box.execute('CREATE TRIGGER r AFTER INSERT ON t FOR EACH ROW BEGIN SELECT 1; END') > +box.execute('INSERT INTO t VALUES (1), (NULL), (10), (NULL), (NULL), (3), (NULL);') Leave explanation why no-op trigger is required. Otherwise it looks redundant. Also, Kirill forces new convention saying that each bug fix should be placed at separate file named gh-xxxx-description. > +box.execute('SELECT * FROM t;') > +box.execute('DROP TABLE t;')
next prev parent reply other threads:[~2020-03-11 15:28 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-01-17 7:59 imeevma 2020-01-20 17:57 ` Nikita Pettik 2020-02-03 14:00 ` Mergen Imeev 2020-02-25 10:17 ` Mergen Imeev 2020-02-25 10:22 ` Mergen Imeev 2020-03-11 15:27 ` Nikita Pettik [this message] 2020-03-23 11:40 ` Mergen Imeev 2020-03-23 11:42 ` Imeev Mergen
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200311152759.GA29797@tarantool.org \ --to=korablev@tarantool.org \ --cc=imeevma@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v1 1/1] sql: use rowid as PK of ephemeral space on INSERT' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox