* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* func_interval.c
*
*
* IDENTIFICATION
* src/ogsql/function/func_interval.c
*
* -------------------------------------------------------------------------
*/
#include "func_interval.h"
static status_t sql_verify_num2interval_core(sql_verifier_t *verf, expr_node_t *func)
{
if (sql_verify_func_node(verf, func, 2, 2, OG_INVALID_ID32) != OG_SUCCESS) {
return OG_ERROR;
}
expr_tree_t *arg1 = func->argument;
if (!sql_match_numeric_type(TREE_DATATYPE(arg1))) {
OG_SRC_ERROR_REQUIRE_NUMERIC(arg1->loc, TREE_DATATYPE(arg1));
return OG_ERROR;
}
expr_tree_t *arg2 = arg1->next;
if (!sql_match_string_type(TREE_DATATYPE(arg2))) {
OG_SRC_ERROR_REQUIRE_STRING(arg2->loc, TREE_DATATYPE(arg2));
return OG_ERROR;
}
return OG_SUCCESS;
}
* Syntax: NUMTOYMINTERVAL(num, 'interval_unit')
* num is a numeric
* interval_unit = {YEAR | MONTH}
*/
status_t sql_verify_numtoyminterval(sql_verifier_t *verf, expr_node_t *func)
{
CM_POINTER2(verf, func);
if (sql_verify_num2interval_core(verf, func) != OG_SUCCESS) {
return OG_ERROR;
}
func->datatype = OG_TYPE_INTERVAL_YM;
func->size = sizeof(interval_ym_t);
func->typmod.year_prec = ITVL_MAX_YEAR_PREC;
return OG_SUCCESS;
}
* Syntax: NUMTOYMINTERVAL(num, 'interval_unit')
* num is a numeric
* interval_unit = {YEAR | MONTH}
*/
status_t sql_func_numtoyminterval(sql_stmt_t *stmt, expr_node_t *func, variant_t *res)
{
variant_t num_var;
variant_t unit_var;
interval_unit_t ym_unit_id;
CM_POINTER2(func, res);
expr_tree_t *arg1 = func->argument;
CM_POINTER(arg1);
SQL_EXEC_FUNC_ARG_EX(arg1, &num_var, res);
if (!OG_IS_WEAK_NUMERIC_TYPE(num_var.type)) {
OG_SRC_ERROR_REQUIRE_NUMERIC(arg1->loc, num_var.type);
return OG_ERROR;
}
if (var_as_real(&num_var) != OG_SUCCESS) {
cm_set_error_loc(arg1->loc);
return OG_ERROR;
}
expr_tree_t *arg2 = arg1->next;
CM_POINTER(arg2);
SQL_EXEC_FUNC_ARG_EX(arg2, &unit_var, res);
if (!OG_IS_STRING_TYPE(unit_var.type)) {
OG_SRC_ERROR_REQUIRE_STRING(arg2->loc, unit_var.type);
return OG_ERROR;
}
ym_unit_id = cm_get_ymitvl_unit(&unit_var.v_text);
if (ym_unit_id == IU_YEAR) {
OG_RETURN_IFERR(cm_year2yminterval(num_var.v_real, &res->v_itvl_ym));
} else if (ym_unit_id == IU_MONTH) {
OG_RETURN_IFERR(cm_month2yminterval(num_var.v_real, &res->v_itvl_ym));
} else {
OG_SRC_THROW_ERROR(arg2->loc, ERR_INVALID_FUNC_PARAMS, "'YEAR' or 'MONTH' expected");
return OG_ERROR;
}
res->is_null = OG_FALSE;
res->type = OG_TYPE_INTERVAL_YM;
return OG_SUCCESS;
}
* Syntax: NUMTODSINTERVAL(num, 'interval_unit')
* num is a numeric
* interval_unit = {DAY | HOUR | MINUTE | SECOND}
*/
status_t sql_verify_numtodsinterval(sql_verifier_t *verf, expr_node_t *func)
{
CM_POINTER2(verf, func);
if (sql_verify_num2interval_core(verf, func) != OG_SUCCESS) {
return OG_ERROR;
}
func->datatype = OG_TYPE_INTERVAL_DS;
func->size = sizeof(interval_ds_t);
func->typmod.day_prec = ITVL_MAX_DAY_PREC;
func->typmod.frac_prec = ITVL_MAX_SECOND_PREC;
return OG_SUCCESS;
}
static status_t sql_num2dsitvl(variant_t *num_var, interval_unit_t ds_unit_id, interval_ds_t *dsitvl)
{
switch (ds_unit_id) {
case IU_DAY:
OG_RETURN_IFERR(cm_day2dsinterval(num_var->v_real, dsitvl));
break;
case IU_HOUR:
OG_RETURN_IFERR(cm_hour2dsinterval(num_var->v_real, dsitvl));
break;
case IU_MINUTE:
OG_RETURN_IFERR(cm_minute2dsinterval(num_var->v_real, dsitvl));
break;
case IU_SECOND:
OG_RETURN_IFERR(cm_second2dsinterval(num_var->v_real, dsitvl));
break;
case IU_NONE:
default:
OG_THROW_ERROR(ERR_INVALID_FUNC_PARAMS, "'DAY', 'HOUR', 'MINUTE' or 'SECOND' expected");
return OG_ERROR;
}
return OG_SUCCESS;
}
* Syntax: NUMTODSINTERVAL(num, 'interval_unit')
* num is a numeric
* interval_unit = {DAY | HOUR | MINUTE | SECOND}
*/
status_t sql_func_numtodsinterval(sql_stmt_t *stmt, expr_node_t *func, variant_t *res)
{
variant_t num_var;
variant_t unit_var;
interval_unit_t ds_unit_id;
CM_POINTER2(func, res);
expr_tree_t *arg1 = func->argument;
CM_POINTER(arg1);
SQL_EXEC_FUNC_ARG_EX(arg1, &num_var, res);
if (!OG_IS_WEAK_NUMERIC_TYPE(num_var.type)) {
OG_SRC_ERROR_REQUIRE_NUMERIC(arg1->loc, num_var.type);
return OG_ERROR;
}
if (var_as_real(&num_var) != OG_SUCCESS) {
cm_set_error_loc(arg1->loc);
return OG_ERROR;
}
expr_tree_t *arg2 = arg1->next;
CM_POINTER(arg2);
SQL_EXEC_FUNC_ARG_EX(arg2, &unit_var, res);
if (!OG_IS_STRING_TYPE(unit_var.type)) {
OG_SRC_ERROR_REQUIRE_STRING(arg2->loc, unit_var.type);
return OG_ERROR;
}
ds_unit_id = cm_get_dsitvl_unit(&unit_var.v_text);
if (sql_num2dsitvl(&num_var, ds_unit_id, &res->v_itvl_ds) != OG_SUCCESS) {
cm_set_error_loc(arg2->loc);
return OG_ERROR;
}
res->is_null = OG_FALSE;
res->type = OG_TYPE_INTERVAL_DS;
return OG_SUCCESS;
}
* The Implementation of the function TO_YMINTERVAL
*/
status_t sql_func_to_yminterval(sql_stmt_t *stmt, expr_node_t *func, variant_t *res)
{
variant_t var1;
CM_POINTER3(stmt, func, res);
expr_tree_t *arg1 = func->argument;
CM_POINTER(arg1);
SQL_EXEC_FUNC_ARG_EX(arg1, &var1, res);
if (!OG_IS_STRING_TYPE(var1.type)) {
OG_SRC_ERROR_REQUIRE_STRING(arg1->loc, var1.type);
return OG_ERROR;
}
res->is_null = OG_FALSE;
res->type = OG_TYPE_INTERVAL_YM;
return cm_text2yminterval(&var1.v_text, &res->v_itvl_ym);
}
static status_t sql_verify_to_interval_core(sql_verifier_t *verf, expr_node_t *func)
{
if (sql_verify_func_node(verf, func, 1, 1, OG_INVALID_ID32) != OG_SUCCESS) {
return OG_ERROR;
}
expr_tree_t *arg1 = func->argument;
if (!sql_match_string_type(TREE_DATATYPE(arg1))) {
OG_SRC_ERROR_REQUIRE_STRING(arg1->loc, TREE_DATATYPE(arg1));
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t sql_verify_to_yminterval(sql_verifier_t *verf, expr_node_t *func)
{
CM_POINTER2(verf, func);
if (sql_verify_to_interval_core(verf, func) != OG_SUCCESS) {
return OG_ERROR;
}
func->datatype = OG_TYPE_INTERVAL_YM;
func->size = sizeof(interval_ym_t);
func->typmod.year_prec = ITVL_MAX_YEAR_PREC;
return OG_SUCCESS;
}
* The Implementation of the function TO_YMINTERVAL
*/
status_t sql_func_to_dsinterval(sql_stmt_t *stmt, expr_node_t *func, variant_t *res)
{
variant_t var1;
CM_POINTER3(stmt, func, res);
expr_tree_t *arg1 = func->argument;
CM_POINTER(arg1);
SQL_EXEC_FUNC_ARG_EX(arg1, &var1, res);
if (!OG_IS_STRING_TYPE(var1.type)) {
OG_SRC_ERROR_REQUIRE_STRING(arg1->loc, var1.type);
return OG_ERROR;
}
res->is_null = OG_FALSE;
res->type = OG_TYPE_INTERVAL_DS;
return cm_text2dsinterval(&var1.v_text, &res->v_itvl_ds);
}
status_t sql_verify_to_dsinterval(sql_verifier_t *verf, expr_node_t *func)
{
CM_POINTER2(verf, func);
if (sql_verify_to_interval_core(verf, func) != OG_SUCCESS) {
return OG_ERROR;
}
func->datatype = OG_TYPE_INTERVAL_DS;
func->size = sizeof(interval_ds_t);
func->typmod.day_prec = ITVL_MAX_DAY_PREC;
func->typmod.frac_prec = ITVL_MAX_SECOND_PREC;
return OG_SUCCESS;
}