From: Chris Sosnin <k.sosnin@tarantool.org>
To: v.shpilevoy@tarantool.org, tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH] sql: provide a user friendly frontend for accessing session settings
Date: Thu, 30 Jan 2020 14:10:09 +0300 [thread overview]
Message-ID: <20200130111009.35857-1-k.sosnin@tarantool.org> (raw)
Currently if a user wants to change session setting with sql, he has
to execute non-obvious query, thus, we introduce a more native way to
do this.
Part of #4711
---
This patch is a follow-up for session settings patchset.
issue:https://github.com/tarantool/tarantool/issues/4711
branch:https://github.com/tarantool/tarantool/tree/ksosnin/gh-4712-search-settings
src/box/sql/build.c | 31 ++++++++++++
src/box/sql/parse.y | 5 ++
src/box/sql/sqlInt.h | 11 +++++
src/box/sql/vdbe.c | 45 +++++++++++++++++
...1-access-settings-from-any-frontend.result | 49 +++++++++++++++++++
...access-settings-from-any-frontend.test.lua | 13 +++++
6 files changed, 154 insertions(+)
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 7dcf7b858..cb7733cfc 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -3474,3 +3474,34 @@ sql_session_settings_init()
setting->set = sql_session_setting_set;
}
}
+
+void
+sql_set_setting(struct Parse *parse_context, struct Token *name,
+ struct Expr *value)
+{
+ struct Vdbe *vdbe = sqlGetVdbe(parse_context);
+ assert(vdbe != NULL);
+ sqlVdbeCountChanges(vdbe);
+ char *key = sql_name_from_token(sql_get(), name);
+ if (key == NULL)
+ goto abort;
+ int low = 0, high = session_setting_MAX - 1;
+ while (low <= high) {
+ int index = (high + low) / 2;
+ int cmp = strcasecmp(session_settings[index].name, key);
+ if (cmp == 0) {
+ sqlVdbeAddOp4(vdbe, OP_Set, index, 0, 0,
+ (const char *)value, P4_PTR);
+ return;
+ }
+ if (cmp < 0)
+ low = index + 1;
+ else
+ high = index - 1;
+ }
+ diag_set(ClientError, ER_SQL_PARSER_GENERIC,
+ tt_sprintf("Session setting %s doesn't exist", key));
+abort:
+ parse_context->is_aborted = true;
+ return;
+}
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index cfe1c0012..9d9b498a7 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1541,6 +1541,11 @@ cmd ::= DROP INDEX ifexists(E) nm(X) ON fullname(Y). {
sql_drop_index(pParse);
}
+///////////////////////////// The SET command ////////////////////////////////
+cmd ::= SET nm(X) EQ term(Y). {
+ sql_set_setting(pParse,&X,Y.pExpr);
+}
+
///////////////////////////// The PRAGMA command /////////////////////////////
//
cmd ::= PRAGMA nm(X). {
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index d1fcf4761..5e192a7bb 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -4510,4 +4510,15 @@ int
sql_fieldno_by_name(struct Parse *parse_context, struct Expr *field_name,
uint32_t *fieldno);
+/**
+ * Create VDBE instructions to set new value of session setting.
+ *
+ * @param parse_context Parsing context.
+ * @param name Name of the session setting.
+ * @param value New value of the session setting.
+ */
+void
+sql_set_setting(struct Parse *parse_context, struct Token *name,
+ struct Expr *value);
+
#endif /* sqlINT_H */
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index eab74db4a..0ee90de47 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -55,6 +55,7 @@
#include "box/schema.h"
#include "box/space.h"
#include "box/sequence.h"
+#include "box/session_settings.h"
/*
* Invoke this macro on memory cells just prior to changing the
@@ -5261,6 +5262,50 @@ case OP_IncMaxid: {
break;
}
+/* Opcode: Set P1 * * P4 *
+ *
+ * Set new value to session setting. P1 is ID of the setting.
+ * P4 is actually of type "struct Expr *" and contains value
+ * of the setting.
+ */
+case OP_Set: {
+ assert(pOp->p4type == P4_PTR);
+ struct Expr *expr = (struct Expr *)pOp->p4.p;
+ int sid = pOp->p1;
+ assert(sid >= 0 && sid < session_setting_MAX);
+ struct session_setting *setting = &session_settings[sid];
+ switch (expr->type) {
+ case FIELD_TYPE_BOOLEAN: {
+ bool value = expr->op == TK_TRUE;
+ size_t size = mp_sizeof_bool(value);
+ char *mp_value = (char *)region_alloc(&fiber()->gc,
+ size);
+ mp_encode_bool(mp_value, value);
+ if (setting->set(sid, mp_value) != 0)
+ goto abort_due_to_error;
+ break;
+ }
+ case FIELD_TYPE_STRING: {
+ const char *str = expr->u.zToken;
+ size_t len = strlen(str);
+ uint32_t size = mp_sizeof_str(len);
+ char *mp_value = (char *)region_alloc(&fiber()->gc,
+ size);
+ mp_encode_str(mp_value, str, len);
+ if (setting->set(sid, mp_value) != 0)
+ goto abort_due_to_error;
+ break;
+ }
+ default:
+ diag_set(ClientError, ER_SESSION_SETTING_INVALID_VALUE,
+ setting->name,
+ field_type_strs[setting->metadata.field_type]);
+ goto abort_due_to_error;
+ }
+ p->nChange++;
+ break;
+}
+
/* Opcode: Noop * * * * *
*
* Do nothing. This instruction is often useful as a jump
diff --git a/test/box/gh-4511-access-settings-from-any-frontend.result b/test/box/gh-4511-access-settings-from-any-frontend.result
index 1c3ca7661..0597365a1 100644
--- a/test/box/gh-4511-access-settings-from-any-frontend.result
+++ b/test/box/gh-4511-access-settings-from-any-frontend.result
@@ -343,6 +343,39 @@ settings.sql_defer_foreign_keys
| - false
| ...
+box.execute([[set sql_default_engine = 'vinyl']])
+ | ---
+ | - row_count: 1
+ | ...
+assert(s:get('sql_default_engine').value == 'vinyl')
+ | ---
+ | - true
+ | ...
+box.execute([[set sql_default_engine = 'memtx']])
+ | ---
+ | - row_count: 1
+ | ...
+assert(s:get('sql_default_engine').value == 'memtx')
+ | ---
+ | - true
+ | ...
+box.execute([[set sql_defer_foreign_keys = true]])
+ | ---
+ | - row_count: 1
+ | ...
+assert(s:get('sql_defer_foreign_keys').value == true)
+ | ---
+ | - true
+ | ...
+box.execute([[set sql_defer_foreign_keys = false]])
+ | ---
+ | - row_count: 1
+ | ...
+assert(s:get('sql_defer_foreign_keys').value == false)
+ | ---
+ | - true
+ | ...
+
settings.sql_default_engine:set(true)
| ---
| - error: Session setting sql_default_engine expected a value of type string
@@ -355,3 +388,19 @@ settings.sql_parser_debug:set('string')
| ---
| - error: Session setting sql_parser_debug expected a value of type boolean
| ...
+
+box.execute([[set sql_def_engine = true]])
+ | ---
+ | - null
+ | - Session setting SQL_DEF_ENGINE doesn't exist
+ | ...
+box.execute([[set sql_default_engine = true]])
+ | ---
+ | - null
+ | - Session setting sql_default_engine expected a value of type string
+ | ...
+box.execute([[set sql_defer_foreign_keys = 'true']])
+ | ---
+ | - null
+ | - Session setting sql_defer_foreign_keys expected a value of type boolean
+ | ...
diff --git a/test/box/gh-4511-access-settings-from-any-frontend.test.lua b/test/box/gh-4511-access-settings-from-any-frontend.test.lua
index 53f03450d..e93edaf98 100644
--- a/test/box/gh-4511-access-settings-from-any-frontend.test.lua
+++ b/test/box/gh-4511-access-settings-from-any-frontend.test.lua
@@ -132,6 +132,19 @@ assert(s:get('sql_defer_foreign_keys').value == true)
s:update('sql_defer_foreign_keys', {{'=', 2, false}})
settings.sql_defer_foreign_keys
+box.execute([[set sql_default_engine = 'vinyl']])
+assert(s:get('sql_default_engine').value == 'vinyl')
+box.execute([[set sql_default_engine = 'memtx']])
+assert(s:get('sql_default_engine').value == 'memtx')
+box.execute([[set sql_defer_foreign_keys = true]])
+assert(s:get('sql_defer_foreign_keys').value == true)
+box.execute([[set sql_defer_foreign_keys = false]])
+assert(s:get('sql_defer_foreign_keys').value == false)
+
settings.sql_default_engine:set(true)
settings.sql_defer_foreign_keys:set(false, 1, 2, 3)
settings.sql_parser_debug:set('string')
+
+box.execute([[set sql_def_engine = true]])
+box.execute([[set sql_default_engine = true]])
+box.execute([[set sql_defer_foreign_keys = 'true']])
--
2.21.1 (Apple Git-122.3)
next reply other threads:[~2020-01-30 11:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-30 11:10 Chris Sosnin [this message]
2020-02-03 22:17 ` Vladislav Shpilevoy
2020-02-04 19:32 ` [Tarantool-patches] [PATCH 4/4] " Chris Sosnin
2020-02-06 22:16 ` Vladislav Shpilevoy
2020-02-07 9:40 ` Chris Sosnin
2020-02-10 22:09 ` Vladislav Shpilevoy
2020-02-17 11:46 ` Chris Sosnin
2020-02-17 11:56 ` Nikita Pettik
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=20200130111009.35857-1-k.sosnin@tarantool.org \
--to=k.sosnin@tarantool.org \
--cc=tarantool-patches@dev.tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH] sql: provide a user friendly frontend for accessing session settings' \
/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