From 7412ecd6c4dc955a1c6c200cf2cfa4464724ef1b Mon Sep 17 00:00:00 2001
From: Nikita Pettik <korablev@tarantool.org>
Date: Tue, 13 Nov 2018 15:32:02 +0300
Subject: [PATCH] sql: don't increment row count on FK creation within CREATE
 or DROP table

We have agreement that each successful DDL operation returns 1 (one) as
a row count (via IProto protocol or changes() SQL function), despite
the number of other created objects (e.g. indexes, sequences, FK
constraints etc).

Needed for #2181
---
 src/box/sql/build.c      | 11 +++++++++--
 test/sql/iproto.result   | 25 ++++++++++++++++++++++---
 test/sql/iproto.test.lua | 11 ++++++++++-
 3 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 5b3348bd21..9c9a6d9e13 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -1415,7 +1415,8 @@ vdbe_emit_fkey_create(struct Parse *parse_context, const struct fkey_def *fk)
 			  constr_tuple_reg + 9);
 	sqlite3VdbeAddOp3(vdbe, OP_SInsert, BOX_FK_CONSTRAINT_ID, 0,
 			  constr_tuple_reg + 9);
-	sqlite3VdbeChangeP5(vdbe, OPFLAG_NCHANGE);
+	if (parse_context->pNewTable == NULL)
+		sqlite3VdbeChangeP5(vdbe, OPFLAG_NCHANGE);
 	save_record(parse_context, BOX_FK_CONSTRAINT_ID, constr_tuple_reg, 2,
 		    vdbe->nOp - 1);
 	sqlite3ReleaseTempRange(parse_context, constr_tuple_reg, 10);
@@ -1809,7 +1810,6 @@ vdbe_emit_fkey_drop(struct Parse *parse_context, char *constraint_name,
 	}
 	sqlite3VdbeAddOp3(vdbe, OP_MakeRecord, key_reg, 2, key_reg + 2);
 	sqlite3VdbeAddOp2(vdbe, OP_SDelete, BOX_FK_CONSTRAINT_ID, key_reg + 2);
-	sqlite3VdbeChangeP5(vdbe, OPFLAG_NCHANGE);
 	VdbeComment((vdbe, "Delete FK constraint %s", constraint_name));
 	sqlite3ReleaseTempRange(parse_context, key_reg, 3);
 }
@@ -2268,6 +2268,13 @@ sql_drop_foreign_key(struct Parse *parse_context, struct SrcList *table,
 	if (constraint_name != NULL)
 		vdbe_emit_fkey_drop(parse_context, constraint_name,
 				    child->def->id);
+	/*
+	 * We account changes to row count only if drop of
+	 * foreign keys take place in a separate
+	 * ALTER TABLE DROP CONSTRAINT statement, since whole
+	 * DROP TABLE always returns 1 (one) as a row count.
+	 */
+	sqlite3VdbeChangeP5(sqlite3GetVdbe(parse_context), OPFLAG_NCHANGE);
 }
 
 /*
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index f390a73a97..e75f791106 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -727,9 +727,6 @@ cn:execute('insert into TEST3 values (null), (null), (null), (null)')
   - -29
   rowcount: 4
 ...
-cn:close()
----
-...
 box.sql.execute('drop table test')
 ---
 ...
@@ -742,6 +739,28 @@ sq:drop()
 box.sql.execute('drop table test3')
 ---
 ...
+--
+-- Ensure that FK inside CREATE TABLE does not affect rowcount.
+--
+cn:execute('create table test (id integer primary key)')
+---
+- rowcount: 1
+...
+cn:execute('create table test2 (id integer primary key, ref integer references test)')
+---
+- rowcount: 1
+...
+cn:execute('drop table test2')
+---
+- rowcount: 1
+...
+cn:execute('drop table test')
+---
+- rowcount: 1
+...
+cn:close()
+---
+...
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 ---
 ...
diff --git a/test/sql/iproto.test.lua b/test/sql/iproto.test.lua
index a18755b005..fb5685a9e5 100644
--- a/test/sql/iproto.test.lua
+++ b/test/sql/iproto.test.lua
@@ -225,12 +225,21 @@ box.sql.execute('create table test3 (id int primary key autoincrement)')
 box.schema.sequence.alter('TEST3', {min=-10000, step=-10})
 cn:execute('insert into TEST3 values (null), (null), (null), (null)')
 
-cn:close()
 box.sql.execute('drop table test')
 s:drop()
 sq:drop()
 box.sql.execute('drop table test3')
 
+--
+-- Ensure that FK inside CREATE TABLE does not affect rowcount.
+--
+cn:execute('create table test (id integer primary key)')
+cn:execute('create table test2 (id integer primary key, ref integer references test)')
+cn:execute('drop table test2')
+cn:execute('drop table test')
+
+cn:close()
+
 box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'create', 'space')
 space = nil
-- 
GitLab