From 76e095488158331e190c41454a446a5d2700b996 Mon Sep 17 00:00:00 2001
From: Denis Smirnov <sd@picodata.io>
Date: Sat, 23 Apr 2022 19:29:28 +0700
Subject: [PATCH] sql: fix string dequoting

Previously,

select "t1"."a" from (select "a" from "t") as "t1";

returned a result column name `t1` instead of `t1.a` because of
incorrect work of a dequoting function. The reason was that
previously sqlDequote() function finished its work when found the
first closing quote.

Old logic worked for simple selects where the column name doesn't
contain an explicit scan name ("a" -> a).
But for the sub-queries results sqlDequote() finished its work right
after the scan name ("t1"."a" -> t1). Now the function continues its
deqouting till it gets the null terminator at the end of the string.

Closes #7063

NO_DOC=don't change any public API, only a bug fix

Co-authored-by: Mergen Imeev <imeevma@gmail.com>
---
 changelogs/unreleased/fix-string-dequoting.md |  4 ++++
 src/box/sql/util.c                            | 12 +++++-----
 test/sql-luatest/gh_7063_dequote_test.lua     | 22 +++++++++++++++++++
 3 files changed, 32 insertions(+), 6 deletions(-)
 create mode 100644 changelogs/unreleased/fix-string-dequoting.md
 create mode 100644 test/sql-luatest/gh_7063_dequote_test.lua

diff --git a/changelogs/unreleased/fix-string-dequoting.md b/changelogs/unreleased/fix-string-dequoting.md
new file mode 100644
index 0000000000..01f28ce410
--- /dev/null
+++ b/changelogs/unreleased/fix-string-dequoting.md
@@ -0,0 +1,4 @@
+## bugfix/sql
+
+* SQL queries with sub-queries and quoted names now return correct column names
+in projection (gh-7063).
diff --git a/src/box/sql/util.c b/src/box/sql/util.c
index c556b9815e..210cb5fb2d 100644
--- a/src/box/sql/util.c
+++ b/src/box/sql/util.c
@@ -80,8 +80,8 @@ sqlStrlen30(const char *z)
  * input does not begin with a quote character, then this routine
  * is a no-op.
  *
- * The input string must be zero-terminated.  A new zero-terminator
- * is added to the dequoted string.
+ * The input string must be zero-terminated. The resulting dequoted
+ * string will also be zero-terminated.
  *
  * The return value is -1 if no dequoting occurs or the length of the
  * dequoted string, exclusive of the zero terminator, if dequoting does
@@ -102,19 +102,19 @@ sqlDequote(char *z)
 	if (!sqlIsquote(quote))
 		return;
 	for (i = 1, j = 0;; i++) {
-		assert(z[i]);
 		if (z[i] == quote) {
 			if (z[i + 1] == quote) {
 				z[j++] = quote;
 				i++;
-			} else {
-				break;
 			}
+		} else if (z[i] == 0) {
+			z[j] = 0;
+			return;
 		} else {
 			z[j++] = z[i];
 		}
+		assert(z[i] != 0);
 	}
-	z[j] = 0;
 }
 
 int
diff --git a/test/sql-luatest/gh_7063_dequote_test.lua b/test/sql-luatest/gh_7063_dequote_test.lua
new file mode 100644
index 0000000000..24750e9554
--- /dev/null
+++ b/test/sql-luatest/gh_7063_dequote_test.lua
@@ -0,0 +1,22 @@
+local server = require('test.luatest_helpers.server')
+local t = require('luatest')
+local g = t.group()
+
+g.before_all(function()
+    g.server = server:new({alias = 'dequote'})
+    g.server:start()
+end)
+
+g.after_all(function()
+    g.server:stop()
+end)
+
+g.test_dequote = function()
+    g.server:exec(function()
+        local t = require('luatest')
+        box.execute([[CREATE TABLE "t"("a" INT PRIMARY KEY);]])
+        local sql = [[SELECT "t1"."a" FROM (SELECT "a" FROM "t") AS "t1";]]
+        t.assert_equals(box.execute(sql).metadata[1].name, 't1.a')
+        box.execute([[DROP TABLE "t";]])
+    end)
+end
-- 
GitLab