From 42c3633194a699ab1a4b5ab00a6853c0aaf0a4e5 Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@gmail.com> Date: Thu, 12 May 2022 18:30:23 +0300 Subject: [PATCH] sql: introduce cast from STRING to DATETIME This patch introduces explicit cast from STRING to DATETIME. Follow-up #6773 NO_DOC=DATETIME has already been introduced. NO_CHANGELOG=DATETIME has already been introduced. --- src/box/sql/mem.c | 14 +++++++++++++ test/sql-luatest/datetime_test.lua | 33 ++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index b8a9d39ca4..3e0e659d6b 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -858,6 +858,18 @@ str_to_dec(struct Mem *mem) return 0; } +/** Convert MEM from STRING to DATETIME. */ +static inline int +str_to_datetime(struct Mem *mem) +{ + assert(mem->type == MEM_TYPE_STR); + struct datetime dt; + if (datetime_parse_full(&dt, mem->z, mem->n, 0) <= 0) + return -1; + mem_set_datetime(mem, &dt); + return 0; +} + static inline int double_to_int(struct Mem *mem) { @@ -1457,6 +1469,8 @@ mem_cast_explicit(struct Mem *mem, enum field_type type) return bin_to_uuid(mem); return -1; case FIELD_TYPE_DATETIME: + if (mem->type == MEM_TYPE_STR) + return str_to_datetime(mem); if (mem->type != MEM_TYPE_DATETIME) return -1; mem->flags = 0; diff --git a/test/sql-luatest/datetime_test.lua b/test/sql-luatest/datetime_test.lua index 29bdf68d41..78cd1d5ab2 100644 --- a/test/sql-luatest/datetime_test.lua +++ b/test/sql-luatest/datetime_test.lua @@ -931,11 +931,12 @@ end g.test_datetime_18_3 = function() g.server:exec(function() local t = require('luatest') + local dt = require('datetime') + local dt1 = dt.new({year = 2001, month = 1, day = 1, hour = 1}) local sql = [[SELECT CAST('2001-01-01T01:00:00Z' AS DATETIME);]] - local res = [[Type mismatch: can not convert ]].. - [[string('2001-01-01T01:00:00Z') to datetime]] - local _, err = box.execute(sql) - t.assert_equals(err.message, res) + local res = {{dt1}} + local rows = box.execute(sql).rows + t.assert_equals(rows, res) end) end @@ -2362,3 +2363,27 @@ g.test_datetime_31_8 = function() t.assert_equals(rows, {{itv3}}) end) end + +-- Make sure cast from STRING to DATETIME works as intended. +g.test_datetime_32_1 = function() + g.server:exec(function() + local t = require('luatest') + local dt = require('datetime') + local dt1 = dt.new({year = 2000, month = 2, day = 29, hour = 1}) + local sql = [[SELECT CAST('2000-02-29T01:00:00Z' AS DATETIME);]] + local res = {{dt1}} + local rows = box.execute(sql).rows + t.assert_equals(rows, res) + end) +end + +g.test_datetime_32_2 = function() + g.server:exec(function() + local t = require('luatest') + local sql = [[SELECT CAST('2001-02-29T01:00:00Z' AS DATETIME);]] + local _, err = box.execute(sql) + local res = [[Type mismatch: can not convert ]].. + [[string('2001-02-29T01:00:00Z') to datetime]] + t.assert_equals(err.message, res) + end) +end -- GitLab