From 9ffb50d55e1f4a1be73b55e7bb24c311ffe1a3ef Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@gmail.com> Date: Thu, 3 Mar 2022 15:54:54 +0300 Subject: [PATCH] sql: allow to bind DATETIME values Part of #6773 NO_DOC=Doc-request will be added in another commit. NO_CHANGELOG=Changelog will be added in another commit. --- src/box/bind.c | 6 ++++-- src/box/bind.h | 3 +++ src/box/lua/execute.c | 4 ++++ src/box/sql/sqlInt.h | 5 +++++ src/box/sql/vdbeapi.c | 10 ++++++++++ test/sql-luatest/datetime_test.lua | 27 +++++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/box/bind.c b/src/box/bind.c index 441c9f46ff..aff2d3d76d 100644 --- a/src/box/bind.c +++ b/src/box/bind.c @@ -189,10 +189,12 @@ sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p, case MP_MAP: return sql_bind_map_static(stmt, pos, p->s, p->bytes); case MP_EXT: - assert(p->ext_type == MP_UUID || p->ext_type == MP_DECIMAL); if (p->ext_type == MP_UUID) return sql_bind_uuid(stmt, pos, &p->uuid); - return sql_bind_dec(stmt, pos, &p->dec); + else if (p->ext_type == MP_DECIMAL) + return sql_bind_dec(stmt, pos, &p->dec); + assert(p->ext_type == MP_DATETIME); + return sql_bind_datetime(stmt, pos, &p->dt); default: unreachable(); } diff --git a/src/box/bind.h b/src/box/bind.h index 45d390314e..be02b7f6ef 100644 --- a/src/box/bind.h +++ b/src/box/bind.h @@ -43,6 +43,7 @@ extern "C" { #include "decimal.h" #include "mp_extension_types.h" #include "tt_uuid.h" +#include "datetime.h" struct sql_stmt; @@ -74,6 +75,8 @@ struct sql_bind { const char *s; struct tt_uuid uuid; decimal_t dec; + /** DATETIME value. */ + struct datetime dt; }; }; diff --git a/src/box/lua/execute.c b/src/box/lua/execute.c index b3f81d709f..ad6d606d78 100644 --- a/src/box/lua/execute.c +++ b/src/box/lua/execute.c @@ -383,6 +383,10 @@ lua_sql_bind_decode(struct lua_State *L, struct sql_bind *bind, int idx, int i) bind->dec = *field.decval; break; } + if (field.ext_type == MP_DATETIME) { + bind->dt = *field.dateval; + break; + } diag_set(ClientError, ER_SQL_BIND_TYPE, "USERDATA", sql_bind_name(bind)); return -1; diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index ac23b7d4f4..3b9f09ba3a 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -77,6 +77,7 @@ #include "trivia/util.h" #include "decimal.h" +#include "datetime.h" /* * These #defines should enable >2GB file support on POSIX if the @@ -568,6 +569,10 @@ sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid); int sql_bind_dec(struct sql_stmt *stmt, int i, const decimal_t *dec); +/** Perform DATETIME parameter binding for the sql statement. */ +int +sql_bind_datetime(struct sql_stmt *stmt, int i, const struct datetime *dt); + /** * Return the number of wildcards that should be bound to. */ diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 060846572f..2316769e19 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -560,6 +560,16 @@ sql_bind_dec(struct sql_stmt *stmt, int i, const decimal_t *dec) return 0; } +int +sql_bind_datetime(struct sql_stmt *stmt, int i, const struct datetime *dt) +{ + struct Vdbe *p = (struct Vdbe *)stmt; + if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "datetime") != 0) + return -1; + mem_set_datetime(&p->aVar[i - 1], dt); + return 0; +} + int sql_bind_parameter_count(const struct sql_stmt *stmt) { diff --git a/test/sql-luatest/datetime_test.lua b/test/sql-luatest/datetime_test.lua index 0e5e1ba276..c0042aec12 100644 --- a/test/sql-luatest/datetime_test.lua +++ b/test/sql-luatest/datetime_test.lua @@ -1587,3 +1587,30 @@ g.test_datetime_27 = function() t.assert_equals(rows, res) end) end + +-- Make sure that DATETIME value can be bound. +g.test_datetime_28_1 = function() + g.server:exec(function() + local t = require('luatest') + local dt = require('datetime') + local dt4 = dt.new({year = 2004, month = 4, day = 4, hour = 4}) + local sql = [[SELECT ?;]] + local res = {{dt4}} + local rows = box.execute(sql, {dt4}).rows + + t.assert_equals(rows, res) + end) +end + +g.test_datetime_28_2 = function() + g.server:exec(function() + local t = require('luatest') + local dt = require('datetime') + local dt4 = dt.new({year = 2004, month = 4, day = 4, hour = 4}) + local sql = [[SELECT $1;]] + local res = {{dt4}} + local rows = box.execute(sql, {dt4}).rows + + t.assert_equals(rows, res) + end) +end -- GitLab