* 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.
* -------------------------------------------------------------------------
*
* expr_parser.h
*
*
* IDENTIFICATION
* src/ogsql/parser/expr_parser.h
*
* -------------------------------------------------------------------------
*/
#ifndef __EXPR_PARSER_H__
#define __EXPR_PARSER_H__
#include "ogsql_expr.h"
#include "scanner.h"
#include "ogsql_cond.h"
#include "knl_database.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum st_timezone_type {
WITHOUT_TIMEZONE,
WITH_TIMEZONE,
WITH_LOCAL_TIMEZONE,
} timezone_type_t;
typedef struct st_interval_info {
typmode_t type;
uint32 fmt;
} interval_info_t;
typedef struct st_type_word {
char *str;
galist_t *typemode;
source_location_t loc;
bool32 is_name_typemode;
bool32 pl_type;
bool32 pl_rowtype;
union {
struct {
timezone_type_t timezone;
};
struct {
galist_t *second_typemde;
};
struct {
int array_size;
uint8 charset;
uint8 collation;
bool8 is_char;
bool8 is_array;
};
};
} type_word_t;
#define IS_DUAL_TABLE_NAME(tab_name) \
(cm_text_str_equal_ins(tab_name, "DUAL") || cm_text_str_equal(tab_name, "SYS_DUMMY"))
static inline status_t sql_word_as_table(sql_stmt_t *stmt, word_t *word, var_word_t *var)
{
if (word->ex_count == 0) {
if (sql_copy_object_name_loc(stmt->context, word->type, &word->text, &var->table.name) != OG_SUCCESS) {
return OG_ERROR;
}
var->table.user.loc = word->text.loc;
var->table.user.implicit = OG_TRUE;
text_t user_name = { stmt->session->curr_schema, (uint32)strlen(stmt->session->curr_schema) };
if (IS_DUAL_TABLE_NAME(&var->table.name.value)) {
cm_text_upper(&var->table.name.value);
}
if (sql_copy_name(stmt->context, &user_name, (text_t *)&var->table.user) != OG_SUCCESS) {
return OG_ERROR;
}
} else if (word->ex_count == 1) {
if (sql_copy_object_name_loc(stmt->context, word->ex_words[0].type, &word->ex_words[0].text,
&var->table.name) != OG_SUCCESS) {
return OG_ERROR;
}
if (sql_copy_name_prefix_tenant_loc(stmt, &word->text, &var->table.user) != OG_SUCCESS) {
return OG_ERROR;
}
var->table.user.implicit = OG_FALSE;
if (cm_text_str_equal_ins(&var->table.user.value, "SYS") && IS_DUAL_TABLE_NAME(&var->table.name.value)) {
cm_text_upper(&var->table.name.value);
}
} else {
OG_SRC_THROW_ERROR(word->text.loc, ERR_SQL_SYNTAX_ERROR, "invalid table name");
return OG_ERROR;
}
return OG_SUCCESS;
}
static inline status_t sql_word_as_column(sql_stmt_t *stmt, word_t *word, var_word_t *var)
{
var->column.ss_start = OG_INVALID_ID32;
var->column.ss_end = OG_INVALID_ID32;
if (word->ex_count == 0) {
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, word->type, &word->text, &var->column.name));
var->column.table.value = CM_NULL_TEXT;
var->column.table.loc = word->text.loc;
var->column.user.value = CM_NULL_TEXT;
var->column.user.loc = word->text.loc;
} else if (word->ex_count == 1) {
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, word->ex_words[0].type, &word->ex_words[0].text,
&var->column.name));
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->type | word->ori_type, &word->text, &var->column.table));
OG_RETURN_IFERR(sql_copy_name_prefix_tenant_loc(stmt, &word->text, &var->column.user_ex));
var->column.user.value = CM_NULL_TEXT;
var->column.user.loc = word->text.loc;
} else if (word->ex_count == 2) {
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, word->ex_words[1].type, &word->ex_words[1].text,
&var->column.name));
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, word->ex_words[0].type, &word->ex_words[0].text,
&var->column.table));
OG_RETURN_IFERR(sql_copy_name_prefix_tenant_loc(stmt, &word->text, &var->column.user));
} else {
OG_SRC_THROW_ERROR(word->text.loc, ERR_SQL_SYNTAX_ERROR, "invalid column name is found");
return OG_ERROR;
}
return OG_SUCCESS;
}
static inline status_t sql_word_as_func(sql_stmt_t *stmt, word_t *word, var_word_t *var_word)
{
if (word->ex_count == 0) {
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->type | word->ori_type, &word->text, &var_word->func.name));
var_word->func.args.value = CM_NULL_TEXT;
var_word->func.args.loc = word->text.loc;
var_word->func.pack.value = CM_NULL_TEXT;
var_word->func.pack.loc = word->text.loc;
var_word->func.user.value = CM_NULL_TEXT;
var_word->func.user.loc = word->text.loc;
} else if (word->ex_count == 1) {
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->type | word->ori_type, &word->text, &var_word->func.name));
var_word->func.args = word->ex_words[0].text;
var_word->func.pack.value = CM_NULL_TEXT;
var_word->func.pack.loc = word->text.loc;
var_word->func.user.value = CM_NULL_TEXT;
var_word->func.user.loc = word->text.loc;
} else if (word->ex_count == 2) {
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, word->ori_type,
&word->text, &var_word->func.org_user));
OG_RETURN_IFERR(sql_copy_object_name_prefix_tenant_loc(stmt, word->ori_type,
&word->text, &var_word->func.user));
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->ex_words[0].type,
&word->ex_words[0].text, &var_word->func.name));
var_word->func.args = word->ex_words[1].text;
var_word->func.pack.value = CM_NULL_TEXT;
var_word->func.pack.loc = word->text.loc;
} else if (word->ex_count == 3) {
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->ex_words[1].type,
&word->ex_words[1].text, &var_word->func.name));
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, word->ex_words[0].type,
&word->ex_words[0].text, &var_word->func.pack));
OG_RETURN_IFERR(sql_copy_name_prefix_tenant_loc(stmt, &word->text, &var_word->func.user));
var_word->func.args = word->ex_words[2].text;
} else {
OG_SRC_THROW_ERROR(word->text.loc, ERR_SQL_SYNTAX_ERROR, "invalid function or procedure name is found");
return OG_ERROR;
}
var_word->func.count = word->ex_count;
return OG_SUCCESS;
}
static inline status_t sql_expr_list_as_func(sql_stmt_t *stmt, galist_t *list, var_word_t *var_word)
{
expr_tree_t *list_expr = cm_galist_get(list, 0);
sql_text_t sql_text;
sql_text.value = list_expr->root->value.v_text;
sql_text.loc = list_expr->root->loc;
if (list->count == 1) {
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, WORD_TYPE_FUNCTION, &sql_text, &var_word->func.name));
var_word->func.args.value = CM_NULL_TEXT;
var_word->func.args.loc = sql_text.loc;
var_word->func.pack.value = CM_NULL_TEXT;
var_word->func.pack.loc = sql_text.loc;
var_word->func.user.value = CM_NULL_TEXT;
var_word->func.user.loc = sql_text.loc;
} else if (list->count == 2) {
OG_RETURN_IFERR(sql_copy_object_name_loc(stmt->context, WORD_TYPE_UNKNOWN,
&sql_text, &var_word->func.org_user));
OG_RETURN_IFERR(sql_copy_object_name_prefix_tenant_loc(stmt, WORD_TYPE_UNKNOWN,
&sql_text, &var_word->func.user));
list_expr = cm_galist_get(list, 1);
sql_text.value = list_expr->root->value.v_text;
sql_text.loc = list_expr->root->loc;
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, WORD_TYPE_FUNCTION, &sql_text, &var_word->func.name));
var_word->func.args.value = CM_NULL_TEXT;
var_word->func.args.loc = sql_text.loc;
var_word->func.pack.value = CM_NULL_TEXT;
var_word->func.pack.loc = sql_text.loc;
} else if (list->count == 3) {
OG_RETURN_IFERR(sql_copy_name_prefix_tenant_loc(stmt, &sql_text, &var_word->func.user));
list_expr = cm_galist_get(list, 1);
sql_text.value = list_expr->root->value.v_text;
sql_text.loc = list_expr->root->loc;
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, WORD_TYPE_UNKNOWN, &sql_text, &var_word->func.pack));
list_expr = cm_galist_get(list, 2);
sql_text.value = list_expr->root->value.v_text;
sql_text.loc = list_expr->root->loc;
OG_RETURN_IFERR(
sql_copy_object_name_loc(stmt->context, WORD_TYPE_FUNCTION, &sql_text, &var_word->func.name));
var_word->func.args.value = CM_NULL_TEXT;
var_word->func.args.loc = sql_text.loc;
} else {
OG_SRC_THROW_ERROR(sql_text.loc, ERR_SQL_SYNTAX_ERROR, "invalid function or procedure name is found");
return OG_ERROR;
}
var_word->func.count = list->count;
return OG_SUCCESS;
}
#define EXPR_EXPECT_NONE 0x00000000
#define EXPR_EXPECT_UNARY_OP 0x00000001
#define EXPR_EXPECT_OPER 0x00000002
#define EXPR_EXPECT_VAR 0x00000004
#define EXPR_EXPECT_UNARY 0x00000008
#define EXPR_EXPECT_STAR 0x00000010
#define EXPR_EXPECT_ALPHA 0x00000020
typedef enum en_parsing_mode {
PM_NORMAL,
PM_PL_VAR,
PM_PL_ARG,
} pmode_t;
status_t sql_init_expr_node(sql_stmt_t *stmt, expr_tree_t **expr, expr_node_t **node,
og_type_t type, expr_node_type_t expr_type, source_location_t loc);
status_t sql_create_expr_tree(sql_stmt_t *stmt, expr_tree_t **expr, og_type_t type, expr_node_type_t expr_type,
source_location_t loc);
status_t sql_create_int_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, int val, source_location_t loc);
status_t sql_create_bigint_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, int64 val, source_location_t loc);
status_t sql_create_float_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, source_location_t loc);
status_t sql_create_binary_float_double_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val,
source_location_t loc);
status_t sql_create_string_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, source_location_t loc);
status_t sql_create_hex_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, source_location_t loc);
status_t sql_create_bool_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, bool32 val, source_location_t loc);
status_t sql_create_null_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, source_location_t loc);
status_t sql_create_datetime_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, uint32 datatype_id,
source_location_t loc);
status_t sql_create_columnref_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, galist_t *list,
expr_node_type_t type, source_location_t loc);
status_t sql_create_indices_expr(sql_stmt_t *stmt, expr_tree_t **expr, int32 start, int32 end, source_location_t loc);
status_t sql_create_paramref_expr(sql_stmt_t *stmt, expr_tree_t **expr, uint32 token_len, lex_location_t lex_loc);
status_t sql_create_case_expr(sql_stmt_t *stmt, expr_tree_t **expr, expr_tree_t* case_arg,
galist_t* case_pair, expr_tree_t* default_expr, source_location_t loc);
status_t sql_expr_tree_to_cond_node(sql_stmt_t *stmt, expr_tree_t *expr, cond_node_t **node);
status_t sql_create_select_expr(sql_stmt_t *stmt, expr_tree_t **expr, sql_select_t *select_ctx, sql_array_t *array,
source_location_t loc);
status_t sql_build_type_expr(sql_stmt_t *stmt, type_word_t *type, expr_tree_t *type_expr);
status_t sql_create_expr_until(sql_stmt_t *stmt, expr_tree_t **expr, word_t *word);
status_t sql_create_expr_from_text(sql_stmt_t *stmt, sql_text_t *text, expr_tree_t **expr, word_flag_t word_flag);
status_t sql_create_expr_list(sql_stmt_t *stmt, sql_text_t *text, expr_tree_t **expr);
status_t sql_create_expr(sql_stmt_t *stmt, expr_tree_t **expr);
status_t sql_add_expr_word(sql_stmt_t *stmt, expr_tree_t *expr, word_t *word);
status_t sql_create_expr_from_word(sql_stmt_t *stmt, word_t *word, expr_tree_t **expr);
status_t sql_generate_expr(expr_tree_t *expr);
status_t sql_parse_typmode(lex_t *lex, pmode_t pmod, typmode_t *typmod, word_t *typword);
status_t sql_parse_datatype(lex_t *lex, pmode_t pmod, typmode_t *typmod, word_t *typword);
status_t sql_parse_datatype_typemode(lex_t *lex, pmode_t pmod, typmode_t *typmod, word_t *typword, word_t *tword);
status_t sql_parse_typmode_bison(char *user, type_word_t *type, pmode_t pmod, typmode_t *typmod, word_t *typword);
status_t sql_parse_case_expr(sql_stmt_t *stmt, word_t *word, expr_node_t *node);
status_t sql_parse_datetime_precision_bison(galist_t *typemode, source_location_t loc, int32 *val_int32,
int32 def_prec, int32 min_prec, int32 max_prec, const char *field_name);
status_t sql_parse_second_precision_bison(galist_t *typemode, source_location_t loc, int32 *lead_prec,
int32 *frac_prec);
status_t sql_build_default_reserved_expr(sql_stmt_t *stmt, expr_tree_t **r_result);
status_t sql_build_column_expr(sql_stmt_t *stmt, knl_column_t *column, expr_tree_t **r_result);
status_t sql_copy_text_remove_quotes(sql_context_t *context, text_t *src, text_t *dst);
status_t sql_word2text(sql_stmt_t *stmt, word_t *word, expr_node_t *node);
status_t sql_word2number(word_t *word, expr_node_t *node);
status_t sql_parse_datatype_typemode_bison(char *user, type_word_t *type, typmode_t *v_type);
#define EXPR_VAR_WORDS \
(WORD_TYPE_VARIANT | WORD_TYPE_FUNCTION | WORD_TYPE_STRING | WORD_TYPE_PARAM | WORD_TYPE_NUMBER | \
WORD_TYPE_RESERVED | WORD_TYPE_DATATYPE | WORD_TYPE_BRACKET | WORD_TYPE_KEYWORD | WORD_TYPE_PL_ATTR | \
WORD_TYPE_PL_NEW_COL | WORD_TYPE_PL_OLD_COL | WORD_TYPE_DQ_STRING | WORD_TYPE_HEXADECIMAL | \
WORD_TYPE_JOIN_COL | WORD_TYPE_ARRAY)
#define EXPR_IS_UNARY_OP(word) \
((word)->type == (uint32)WORD_TYPE_OPERATOR && ((word)->id == (uint32)OPER_TYPE_SUB || \
(word)->id == (uint32)OPER_TYPE_ADD || (word)->id == (uint32)OPER_TYPE_PRIOR))
#define EXPR_IS_UNARY_OP_ROOT(word) \
((word)->type == (uint32)WORD_TYPE_OPERATOR && ((word)->id == (uint32)OPER_TYPE_ROOT))
#define EXPR_IS_OPER(word) ((word)->type == (uint32)WORD_TYPE_OPERATOR)
#define EXPR_IS_STAR(word) \
((word)->text.len > 0 && CM_TEXT_END(&(word)->text) == '*' && \
(word)->type != WORD_TYPE_DQ_STRING)
status_t sql_add_param_mark(sql_stmt_t *stmt, word_t *word, bool32 *is_repeated, uint32 *pnid);
status_t sql_create_star_expr(sql_stmt_t *stmt, expr_tree_t **expr, lex_location_t loc);
status_t sql_create_prior_expr(sql_stmt_t *stmt, expr_tree_t **expr, expr_node_t *column, source_location_t loc);
status_t sql_create_negative_expr(sql_stmt_t *stmt, expr_tree_t **expr, expr_node_t *operand, source_location_t loc);
status_t sql_create_oper_expr(sql_stmt_t *stmt, expr_tree_t **expr, expr_node_t *left, expr_node_t *right,
expr_node_type_t node_type, source_location_t loc);
status_t sql_create_array_expr(sql_stmt_t *stmt, expr_tree_t **expr, expr_tree_t *array_elements,
source_location_t loc);
status_t sql_create_interval_const_expr(sql_stmt_t *stmt, expr_tree_t **expr, const char* val, interval_info_t info,
source_location_t loc);
status_t sql_create_reserved_expr(sql_stmt_t *stmt, expr_tree_t **expr, uint32 res_id, bool32 namable,
source_location_t loc);
#ifdef __cplusplus
}
#endif
#endif