* 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.
* -------------------------------------------------------------------------
*
* base_compiler.c
*
*
* IDENTIFICATION
* src/ogsql/pl/parser/base_compiler.c
*
* -------------------------------------------------------------------------
*/
#include "base_compiler.h"
#include "pl_memory.h"
void pl_check_and_set_loc(source_location_t source_loc)
{
int32 l_code;
const char *l_message = NULL;
source_location_t l_loc;
cm_get_error(&l_code, &l_message, &l_loc);
if (l_loc.line == 0) {
cm_set_error_loc(source_loc);
l_loc = source_loc;
}
if (g_tls_plc_error.plc_flag) {
cm_set_superposed_plc_loc(l_loc, l_code, l_message);
}
}
status_t plc_stack_safe(pl_compiler_t *compiler)
{
if (sql_stack_safe(compiler->stmt) != OG_SUCCESS) {
pl_check_and_set_loc(compiler->line_loc);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t plc_verify_expr_node(pl_compiler_t *compiler, expr_node_t *node, void *line, uint32 excl_flags)
{
sql_verifier_t verif = { 0 };
verif.context = compiler->stmt->context;
verif.stmt = compiler->stmt;
verif.line = line;
verif.excl_flags = excl_flags;
if (compiler->root_type == PL_PACKAGE_BODY) {
verif.obj = compiler->obj;
}
if (sql_verify_expr_node(&verif, node) != OG_SUCCESS) {
pl_check_and_set_loc(node->loc);
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t plc_clone_expr_node(pl_compiler_t *compiler, expr_node_t **src_node)
{
expr_node_t *dst_node = NULL;
OG_RETURN_IFERR(sql_clone_expr_node(compiler->entity, *src_node, &dst_node, pl_alloc_mem));
*src_node = dst_node;
return OG_SUCCESS;
}
status_t plc_clone_cond_tree(pl_compiler_t *compiler, cond_tree_t **src_cond)
{
cond_tree_t *dst_cond = NULL;
OG_RETURN_IFERR(sql_clone_cond_tree(compiler->entity, *src_cond, &dst_cond, pl_alloc_mem));
*src_cond = dst_cond;
return OG_SUCCESS;
}
status_t plc_clone_expr_tree(pl_compiler_t *compiler, expr_tree_t **src_expr)
{
expr_tree_t *dst_expr = NULL;
OG_RETURN_IFERR(sql_clone_expr_tree(compiler->entity, *src_expr, &dst_expr, pl_alloc_mem));
*src_expr = dst_expr;
return OG_SUCCESS;
}
status_t plc_verify_limit_expr(pl_compiler_t *compiler, expr_tree_t *expr)
{
uint32 excl_flags = SQL_LIMIT_EXCL;
return plc_verify_expr_node(compiler, expr->root, NULL, excl_flags);
}
status_t plc_verify_cond(pl_compiler_t *compiler, cond_tree_t *cond)
{
sql_verifier_t verif = { 0 };
verif.stmt = compiler->stmt;
verif.context = compiler->stmt->context;
if (compiler->root_type == PL_PACKAGE_BODY) {
verif.obj = compiler->obj;
}
verif.excl_flags = SQL_EXCL_AGGR | SQL_EXCL_STAR | SQL_EXCL_JOIN | SQL_EXCL_ROWNUM | SQL_EXCL_ROWID |
SQL_EXCL_DEFAULT | SQL_EXCL_SUBSELECT | SQL_EXCL_COLUMN | SQL_EXCL_ROWSCN | SQL_EXCL_WIN_SORT |
SQL_EXCL_GROUPING | SQL_EXCL_ROWNODEID | SQL_EXCL_METH_PROC | SQL_EXCL_PL_PROC;
if (sql_verify_cond(&verif, cond) != OG_SUCCESS) {
pl_check_and_set_loc(cond->loc);
return OG_ERROR;
}
return OG_SUCCESS;
}
static void plc_concat_join_col_word(text_t *text, uint32 max_len, word_t *word)
{
int32 i;
cm_concat_text(text, max_len, (text_t *)&word->text);
for (i = 0; i < (int32)word->ex_count; i++) {
(void)cm_concat_string(text, max_len, ".");
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
cm_concat_text(text, max_len, &word->ex_words[i].text.value);
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
}
(void)cm_concat_string(text, max_len, "(+)");
}
static void plc_concat_func_word(text_t *text, uint32 max_len, word_t *word)
{
int32 i;
cm_concat_text(text, max_len, (text_t *)&word->text);
for (i = 0; i < (int32)word->ex_count - 1; i++) {
(void)cm_concat_string(text, max_len, ".");
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
cm_concat_text(text, max_len, &word->ex_words[i].text.value);
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
}
(void)cm_concat_string(text, max_len, "(");
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
cm_concat_text(text, max_len, &word->ex_words[i].text.value);
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
(void)cm_concat_string(text, max_len, ")");
}
void plc_concat_word_ex(text_t *text, uint32 max_len, word_t *word)
{
PLC_CONCAT_QUOTATION(text, word->type);
cm_concat_text(text, max_len, (text_t *)&word->text);
PLC_CONCAT_QUOTATION(text, word->type);
for (uint32 i = 0; i < word->ex_count; i++) {
(void)cm_concat_string(text, max_len, ".");
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
cm_concat_text(text, max_len, &word->ex_words[i].text.value);
PLC_CONCAT_QUOTATION(text, word->ex_words[i].type);
}
}
void plc_concat_word(text_t *text, uint32 max_len, word_t *word)
{
if (word->type == WORD_TYPE_FUNCTION) {
plc_concat_func_word(text, max_len, word);
} else if (word->type == WORD_TYPE_ARRAY) {
cm_concat_text(text, max_len, &word->text.value);
} else if (word->type == WORD_TYPE_JOIN_COL) {
plc_concat_join_col_word(text, max_len, word);
} else {
plc_concat_word_ex(text, max_len, word);
}
}
status_t plc_verify_word_as_var(pl_compiler_t *compiler, word_t *word)
{
if (word->text.len > OG_MAX_NAME_LEN) {
OG_SRC_THROW_ERROR(word->loc, ERR_NAME_TOO_LONG, "variant", word->text.len, OG_MAX_NAME_LEN);
return OG_ERROR;
}
for (uint32 i = 0; i < word->ex_count; i++) {
if (word->ex_words[i].text.len > OG_MAX_NAME_LEN) {
OG_SRC_THROW_ERROR(word->loc, ERR_NAME_TOO_LONG, "variant", (int32)word->ex_words[i].text.len,
(int32)OG_MAX_NAME_LEN);
return OG_ERROR;
}
}
return OG_SUCCESS;
}
void plc_try_verify_word_as_var(word_t *word, bool32 *result)
{
*result = OG_TRUE;
if (word->text.len > OG_MAX_NAME_LEN) {
*result = OG_FALSE;
return;
}
for (uint32 i = 0; i < word->ex_count; i++) {
if (word->ex_words[i].text.len > OG_MAX_NAME_LEN) {
*result = OG_FALSE;
return;
}
}
}
status_t pl_save_lex(sql_stmt_t *stmt, lex_t **bak)
{
uint32 lex_size = LEX_HEAD_SIZE + sizeof(uint32);
lex_size = lex_size + (stmt->session->lex->stack.depth) * sizeof(lex_stack_item_t);
if (sql_push(stmt, lex_size, (void **)bak) != OG_SUCCESS) {
return OG_ERROR;
}
errno_t ret = memcpy_s((*bak), lex_size, stmt->session->lex, lex_size);
if (ret != EOK) {
OGSQL_POP(stmt);
OG_THROW_ERROR(ERR_SYSTEM_CALL, ret);
return OG_ERROR;
}
return OG_SUCCESS;
}
void pl_restore_lex(sql_stmt_t *stmt, lex_t *bak)
{
uint32 lex_size = LEX_HEAD_SIZE + sizeof(uint32);
lex_size = lex_size + (bak->stack.depth) * sizeof(lex_stack_item_t);
errno_t ret = memcpy_s(stmt->session->lex, lex_size, bak, lex_size);
if (ret != EOK) {
OG_THROW_ERROR(ERR_SYSTEM_CALL, ret);
}
return;
}