* 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.
* -------------------------------------------------------------------------
*
* ogsql_serial.c
*
*
* IDENTIFICATION
* src/ogsql/node/ogsql_serial.c
*
* -------------------------------------------------------------------------
*/
#include "cm_base.h"
#include "cm_list.h"
#include "ogsql_serial.h"
#include "ogsql_func.h"
#include "ogsql_package.h"
static status_t inline sr_alloc_mem(memory_context_t *ogx, uint32 size, void **ptr)
{
if (ogx->pool->mem_alloc.ogx != NULL) {
OG_RETURN_IFERR(ogx->pool->mem_alloc.mem_func(ogx->pool->mem_alloc.ogx, ogx, size, ptr));
} else {
OG_RETURN_IFERR(mctx_alloc(ogx, size, ptr));
}
if (size != 0) {
MEMS_RETURN_IFERR(memset_s(*ptr, size, 0, size));
}
return OG_SUCCESS;
}
status_t sr_encode_variant(sql_stmt_t *stmt, serializer_t *sr, variant_t *var, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, var, offset);
if (var->is_null) {
*offset = SR_NULL;
return OG_SUCCESS;
}
SR_PUT_FIXED(sr, og_type_t, var->type);
switch (var->type) {
case OG_TYPE_UINT32:
SR_PUT_FIXED(sr, uint32, var->v_uint32);
break;
case OG_TYPE_INTEGER:
SR_PUT_FIXED(sr, int32, var->v_int);
break;
case OG_TYPE_BOOLEAN:
SR_PUT_FIXED(sr, bool32, var->v_bool);
break;
case OG_TYPE_BIGINT:
SR_PUT_FIXED(sr, int64, var->v_bigint);
break;
case OG_TYPE_REAL:
SR_PUT_FIXED(sr, double, var->v_real);
break;
case OG_TYPE_DATE:
SR_PUT_DATA(sr, &var->v_date, sizeof(date_t));
break;
case OG_TYPE_TIMESTAMP:
case OG_TYPE_TIMESTAMP_TZ_FAKE:
SR_PUT_DATA(sr, &var->v_tstamp, sizeof(timestamp_t));
break;
case OG_TYPE_TIMESTAMP_LTZ:
SR_PUT_DATA(sr, &var->v_tstamp_ltz, sizeof(timestamp_ltz_t));
break;
case OG_TYPE_TIMESTAMP_TZ:
SR_PUT_DATA(sr, &var->v_tstamp_tz, sizeof(timestamp_tz_t));
break;
case OG_TYPE_INTERVAL_DS:
SR_PUT_DATA(sr, &var->v_itvl_ds, sizeof(interval_ds_t));
break;
case OG_TYPE_INTERVAL_YM:
SR_PUT_DATA(sr, &var->v_itvl_ym, sizeof(interval_ym_t));
break;
case OG_TYPE_NUMBER:
case OG_TYPE_DECIMAL: {
dec4_t d4;
OG_RETURN_IFERR(cm_dec_8_to_4(&d4, &var->v_dec));
uint32 len = cm_dec4_stor_sz(&d4);
SR_PUT_VARLEN(sr, &d4, len);
break;
}
case OG_TYPE_NUMBER2: {
dec2_t d2;
OG_RETURN_IFERR(cm_dec_8_to_2(&d2, &var->v_dec));
uint32 len = cm_dec2_stor_sz(&d2);
SR_PUT_VARLEN(sr, GET_PAYLOAD(&d2), len);
break;
}
case OG_TYPE_TYPMODE:
SR_PUT_DATA(sr, &var->v_type, sizeof(typmode_t));
break;
case OG_TYPE_ITVL_UNIT:
SR_PUT_DATA(sr, &var->v_itvl_unit_id, sizeof(interval_unit_t));
break;
case OG_TYPE_BLOB:
case OG_TYPE_CLOB:
case OG_TYPE_IMAGE:
break;
case OG_TYPE_STRING:
default:
SR_PUT_VARLEN(sr, var->v_text.str, var->v_text.len);
break;
}
return OG_SUCCESS;
}
static status_t sr_encode_func(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
sql_func_t *func = NULL;
sql_package_t *pack = NULL;
char buf[OG_NAME_BUFFER_SIZE * 2];
text_t text;
uint32 max_len = OG_NAME_BUFFER_SIZE * 2;
text.str = buf;
text.len = 0;
if (node->value.v_func.pack_id != OG_INVALID_ID32) {
pack = sql_get_pack(node->value.v_func.pack_id);
cm_concat_text(&text, max_len, &pack->name);
}
OG_RETURN_IFERR(cm_concat_string(&text, max_len, "."));
func = sql_get_func(&node->value.v_func);
cm_concat_text(&text, max_len, &func->name);
SR_PUT_VARLEN(sr, text.str, text.len);
return OG_SUCCESS;
}
static status_t sr_encode_user_func(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
char buf[OG_NAME_BUFFER_SIZE * 3];
text_t text;
var_udo_t *obj = sql_node_get_obj(node);
uint32 max_len = OG_NAME_BUFFER_SIZE * 3;
text.str = buf;
text.len = 0;
cm_concat_text(&text, max_len, &obj->user);
OG_RETURN_IFERR(cm_concat_string(&text, max_len, "."));
if (!CM_IS_EMPTY(&obj->pack)) {
cm_concat_text(&text, max_len, &obj->pack);
OG_RETURN_IFERR(cm_concat_string(&text, max_len, "."));
}
cm_concat_text(&text, max_len, &obj->name);
SR_PUT_VARLEN(sr, text.str, text.len);
return OG_SUCCESS;
}
* \brief Encode and serialize an expr node
*/
static status_t sr_encode_sequence(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
var_seq_t *seq = &node->value.v_seq;
SR_PUT_VARLEN(sr, seq->user.str, seq->user.len);
SR_PUT_VARLEN(sr, seq->name.str, seq->name.len);
SR_PUT_FIXED(sr, seq_mode_t, seq->mode);
return OG_SUCCESS;
}
#ifdef OG_RAC_ING
static status_t sr_encode_column(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
var_column_t *col = &node->value.v_col;
SR_PUT_FIXED(sr, uint16, col->col);
SR_PUT_FIXED(sr, uint16, col->tab);
SR_PUT_FIXED(sr, og_type_t, col->datatype);
return OG_SUCCESS;
}
static status_t sr_decode_column(const char *sr_data, uint32 temp_offset, variant_t *var)
{
uint32 offset = temp_offset;
var_column_t *col = &var->v_col;
col->col = *((uint16 *)(sr_data + offset));
offset += CM_ALIGN4(sizeof(uint16));
col->tab = *((uint16 *)(sr_data + offset));
offset += CM_ALIGN4(sizeof(uint16));
col->datatype = *(og_type_t *)(sr_data + offset);
var->type = OG_TYPE_COLUMN;
return OG_SUCCESS;
}
#endif
static status_t sr_encode_list(sql_stmt_t *stmt, serializer_t *sr, galist_t *list, uint32 *offset,
sr_encode_cell_t encode_cell)
{
sr_list_t *sr_list = NULL;
uint32 size;
pointer_t cell;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT_LIST(sr, list->count, offset);
size = sizeof(sr_list_t) + list->count * sizeof(uint32);
OG_RETURN_IFERR(sr_push(sr, size, (void **)&sr_list));
sr_list->count = list->count;
for (uint32 i = 0; i < list->count; i++) {
cell = cm_galist_get(list, i);
OG_RETURN_IFERR(encode_cell(stmt, sr, cell, &sr_list->cell[i]));
}
return OG_SUCCESS;
}
static status_t sr_decode_list(memory_context_t *ogx, char *sr_data, uint32 offset, galist_t *list,
sr_decode_cell_t decode_cell)
{
if (offset == SR_NULL) {
list->count = 0;
return OG_SUCCESS;
}
sr_list_t *sr_list = (sr_list_t *)(sr_data + offset);
for (uint32 i = 0; i < sr_list->count; i++) {
OG_RETURN_IFERR(decode_cell(ogx, sr_data, sr_list->cell[i], list));
}
return OG_SUCCESS;
}
static status_t sr_encode_simple_case_pair(sql_stmt_t *stmt, serializer_t *sr, void *context, uint32 *offset)
{
case_pair_t *case_pair = (case_pair_t *)context;
sr_case_pair_t *sr_pair = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, case_pair, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_case_pair_t), (void **)&sr_pair));
OG_RETURN_IFERR(sr_encode_expr(stmt, sr, case_pair->when_expr, &sr_pair->when_expr));
return sr_encode_expr(stmt, sr, case_pair->value, &sr_pair->value);
}
static status_t sr_encode_searched_case_pair(sql_stmt_t *stmt, serializer_t *sr, void *context, uint32 *offset)
{
case_pair_t *case_pair = (case_pair_t *)context;
sr_case_pair_t *sr_pair = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, case_pair, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_case_pair_t), (void **)&sr_pair));
OG_RETURN_IFERR(sr_encode_cond(stmt, sr, case_pair->when_cond, &sr_pair->when_cond));
return sr_encode_expr(stmt, sr, case_pair->value, &sr_pair->value);
}
static status_t sr_encode_case_when(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
case_expr_t *case_expr = (case_expr_t *)VALUE(pointer_t, &node->value);
sr_case_expr_t *sr_case_expr = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, case_expr, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_case_expr_t), (void **)&sr_case_expr));
sr_case_expr->is_cond = case_expr->is_cond;
if (!sr_case_expr->is_cond) {
OG_RETURN_IFERR(sr_encode_expr(stmt, sr, case_expr->expr, &sr_case_expr->expr));
OG_RETURN_IFERR(sr_encode_list(stmt, sr, &case_expr->pairs, &sr_case_expr->pairs, sr_encode_simple_case_pair));
} else {
OG_RETURN_IFERR(
sr_encode_list(stmt, sr, &case_expr->pairs, &sr_case_expr->pairs, sr_encode_searched_case_pair));
}
return sr_encode_expr(stmt, sr, case_expr->default_expr, &sr_case_expr->default_expr);
}
status_t sr_encode_expr_node(sql_stmt_t *stmt, serializer_t *sr, expr_node_t *node, uint32 *offset)
{
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
sr_expr_node_t *sr_node = NULL;
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_expr_node_t), (void **)&sr_node));
sr_node->type = node->type;
sr_node->datatype = node->datatype;
sr_node->unary = node->unary;
sr_node->format_json = node->format_json;
sr_node->json_func_attr = node->json_func_attr;
if (node->type == EXPR_NODE_FUNC || node->type == EXPR_NODE_USER_FUNC) {
OG_RETURN_IFERR(sr_encode_expr(stmt, sr, node->argument, &sr_node->args));
}
switch (node->type) {
case EXPR_NODE_CONST:
case EXPR_NODE_RESERVED:
OG_RETURN_IFERR(sr_encode_variant(stmt, sr, &node->value, &sr_node->value));
break;
case EXPR_NODE_SEQUENCE:
OG_RETURN_IFERR(sr_encode_sequence(stmt, sr, node, &sr_node->value));
break;
case EXPR_NODE_FUNC:
OG_RETURN_IFERR(sr_encode_func(stmt, sr, node, &sr_node->value));
if (IS_BUILDIN_FUNCTION(node, ID_FUNC_ITEM_TRIM)) {
sr_node->ext_args = node->ext_args;
}
if (IS_BUILDIN_FUNCTION(node, ID_FUNC_ITEM_IF) || IS_BUILDIN_FUNCTION(node, ID_FUNC_ITEM_LNNVL)) {
OG_RETURN_IFERR(sr_encode_cond(stmt, sr, (cond_tree_t *)node->cond_arg, &sr_node->cond_arg));
}
break;
case EXPR_NODE_USER_FUNC:
OG_RETURN_IFERR(sr_encode_user_func(stmt, sr, node, &sr_node->value));
break;
case EXPR_NODE_CASE:
OG_RETURN_IFERR(sr_encode_case_when(stmt, sr, node, &sr_node->value));
break;
case EXPR_NODE_ADD:
case EXPR_NODE_SUB:
case EXPR_NODE_MUL:
case EXPR_NODE_DIV:
case EXPR_NODE_MOD:
case EXPR_NODE_CAT:
case EXPR_NODE_BITAND:
case EXPR_NODE_BITOR:
case EXPR_NODE_BITXOR:
case EXPR_NODE_LSHIFT:
case EXPR_NODE_RSHIFT:
OG_RETURN_IFERR(sr_encode_expr_node(stmt, sr, node->left, &sr_node->left));
OG_RETURN_IFERR(sr_encode_expr_node(stmt, sr, node->right, &sr_node->right));
break;
case EXPR_NODE_NEGATIVE:
OG_RETURN_IFERR(sr_encode_expr_node(stmt, sr, node->right, &sr_node->right));
break;
#ifdef OG_RAC_ING
case EXPR_NODE_COLUMN:
case EXPR_NODE_DIRECT_COLUMN:
OG_RETURN_IFERR(sr_encode_column(stmt, sr, node, &sr_node->value));
break;
case EXPR_NODE_STAR:
break;
#endif
case EXPR_NODE_ARRAY:
break;
default:
OG_THROW_ERROR(ERR_SQL_SYNTAX_ERROR, "invalid symbol for serialization");
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t sr_encode_expr(sql_stmt_t *stmt, serializer_t *sr, expr_tree_t *expr, uint32 *offset)
{
sr_expr_tree_t *sr_expr = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, expr, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_expr_tree_t), (void **)&sr_expr));
OG_RETURN_IFERR(sr_encode_expr_node(stmt, sr, expr->root, &sr_expr->root));
return sr_encode_expr(stmt, sr, expr->next, &sr_expr->next);
}
status_t sr_encode_expr_list(sql_stmt_t *stmt, serializer_t *sr, uint32 *offset, int num, ...)
{
sr_list_t *sr_list = NULL;
va_list list;
int i = num;
uint32 size;
serializer_t move_sr = *sr;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT_LIST(sr, num, offset);
size = sizeof(sr_list_t) + num * sizeof(uint32);
OG_RETURN_IFERR(sr_push(sr, size, (void **)&sr_list));
sr_list->count = num;
va_start(list, num);
for (i = 0; i < num; i++) {
expr_tree_t *expr = va_arg(list, expr_tree_t *);
sr_list->cell[i] = sr->pos;
SR_MOVE_STEP(&move_sr, sr);
if (sr_encode_expr(stmt, &move_sr, expr, offset) != OG_SUCCESS) {
va_end(list);
return OG_ERROR;
}
sr->pos += move_sr.pos;
}
va_end(list);
return OG_SUCCESS;
}
static status_t sr_encode_cmp_node(sql_stmt_t *stmt, serializer_t *sr, cmp_node_t *node, uint32 *offset)
{
sr_cmp_node_t *sr_node = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_cmp_node_t), (void **)&sr_node));
sr_node->join_type = node->join_type;
sr_node->type = node->type;
OG_RETURN_IFERR(sr_encode_expr(stmt, sr, node->left, &sr_node->left));
return sr_encode_expr(stmt, sr, node->right, &sr_node->right);
}
static status_t sr_encode_cond_node(sql_stmt_t *stmt, serializer_t *sr, cond_node_t *node, uint32 *offset)
{
sr_cond_node_t *sr_node = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, node, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_cond_node_t), (void **)&sr_node));
sr_node->type = node->type;
switch (node->type) {
case COND_NODE_COMPARE:
OG_RETURN_IFERR(sr_encode_cmp_node(stmt, sr, node->cmp, &sr_node->cmp));
break;
case COND_NODE_TRUE:
case COND_NODE_FALSE:
break;
default:
OG_RETURN_IFERR(sr_encode_cond_node(stmt, sr, node->left, &sr_node->left));
OG_RETURN_IFERR(sr_encode_cond_node(stmt, sr, node->right, &sr_node->right));
break;
}
return OG_SUCCESS;
}
status_t sr_encode_cond(sql_stmt_t *stmt, serializer_t *sr, cond_tree_t *cond, uint32 *offset)
{
sr_cond_tree_t *sr_cond = NULL;
OG_RETURN_IFERR(sql_stack_safe(stmt));
SR_CHECK_OBJECT(sr, cond, offset);
OG_RETURN_IFERR(sr_push(sr, sizeof(sr_cond_tree_t), (void **)&sr_cond));
sr_cond->rownum_upper = cond->rownum_upper;
sr_cond->loc = cond->loc;
return sr_encode_cond_node(stmt, sr, cond->root, &sr_cond->root);
}
status_t sr_decode_variant(char *sr_data, uint32 temp_offset, variant_t *var)
{
uint32 offset = temp_offset;
if (offset == SR_NULL) {
var->type = OG_TYPE_INTEGER;
var->is_null = OG_TRUE;
return OG_SUCCESS;
}
var->is_null = OG_FALSE;
var->type = *(og_type_t *)(sr_data + offset);
offset += CM_ALIGN4(sizeof(og_type_t));
switch (var->type) {
case OG_TYPE_UINT32:
var->v_uint32 = *(uint32 *)(sr_data + offset);
break;
case OG_TYPE_INTEGER:
var->v_int = *(int32 *)(sr_data + offset);
break;
case OG_TYPE_BOOLEAN:
var->v_bool = *(bool32 *)(sr_data + offset);
break;
case OG_TYPE_BIGINT:
var->v_bigint = *(int64 *)(sr_data + offset);
break;
case OG_TYPE_REAL:
var->v_real = *(double *)(sr_data + offset);
break;
case OG_TYPE_DATE:
MEMS_RETURN_IFERR(memcpy_s(&var->v_date, sizeof(date_t), sr_data + offset, sizeof(date_t)));
break;
case OG_TYPE_TIMESTAMP:
case OG_TYPE_TIMESTAMP_TZ_FAKE:
case OG_TYPE_TIMESTAMP_LTZ:
MEMS_RETURN_IFERR(memcpy_s(&var->v_tstamp, sizeof(timestamp_t), sr_data + offset, sizeof(timestamp_t)));
break;
case OG_TYPE_TIMESTAMP_TZ:
MEMS_RETURN_IFERR(
memcpy_s(&var->v_tstamp_tz, sizeof(timestamp_tz_t), sr_data + offset, sizeof(timestamp_tz_t)));
break;
case OG_TYPE_INTERVAL_DS:
MEMS_RETURN_IFERR(
memcpy_s(&var->v_itvl_ds, sizeof(interval_ds_t), sr_data + offset, sizeof(interval_ds_t)));
break;
case OG_TYPE_INTERVAL_YM:
MEMS_RETURN_IFERR(
memcpy_s(&var->v_itvl_ym, sizeof(interval_ym_t), sr_data + offset, sizeof(interval_ym_t)));
break;
case OG_TYPE_NUMBER:
case OG_TYPE_DECIMAL: {
uint32 len = *(uint32 *)(sr_data + offset);
void *data_ptr = (void *)(sr_data + offset + sizeof(uint32));
return cm_dec_4_to_8(&var->v_dec, data_ptr, len);
}
case OG_TYPE_NUMBER2: {
uint32 len = *(uint32 *)(sr_data + offset);
void *data_ptr = (void *)(sr_data + offset + sizeof(uint32));
return cm_dec_2_to_8(&var->v_dec, (const payload_t *)data_ptr, len);
}
case OG_TYPE_TYPMODE: {
MEMS_RETURN_IFERR(memcpy_s(&var->v_type, sizeof(typmode_t), sr_data + offset, sizeof(typmode_t)));
break;
}
case OG_TYPE_ITVL_UNIT: {
MEMS_RETURN_IFERR(
memcpy_s(&var->v_itvl_unit_id, sizeof(interval_unit_t), sr_data + offset, sizeof(interval_unit_t)));
break;
}
case OG_TYPE_STRING:
default:
var->v_text.len = *(uint32 *)(sr_data + offset);
var->v_text.str = (sr_data + offset + sizeof(uint32));
break;
}
return OG_SUCCESS;
}
static void sr_decode_func(char *sr_data, uint32 offset, variant_t *var)
{
text_t text;
text_t pack_name;
text_t func_name;
text.len = *(uint32 *)(sr_data + offset);
text.str = (sr_data + offset + sizeof(uint32));
cm_split_text(&text, '.', '\0', &pack_name, &func_name);
var->type = OG_TYPE_INTEGER;
if (pack_name.len == 0) {
var->v_func.func_id = (uint32)sql_get_func_id(&func_name);
var->v_func.pack_id = OG_INVALID_ID32;
var->v_func.orig_func_id = OG_INVALID_ID32;
} else {
sql_convert_pack_func(&pack_name, &func_name, &var->v_func);
}
}
static status_t sr_decode_user_func(memory_context_t *ogx, char *sr_data, uint32 offset, variant_t *var)
{
text_t text;
text_t pack_or_user;
text_t user;
text_t pack_name;
text_t func_name;
var_udo_t *object = NULL;
text.len = *(uint32 *)(sr_data + offset);
text.str = (sr_data + offset + sizeof(uint32));
(void)cm_split_rtext(&text, '.', '\0', &pack_or_user, &func_name);
(void)cm_split_rtext(&pack_or_user, '.', '\0', &user, &pack_name);
var->type = OG_TYPE_INTEGER;
var->type_for_pl = VAR_UDO;
OG_RETURN_IFERR(sr_alloc_mem(ogx, sizeof(expr_node_t), (void **)&var->v_udo));
object = var->v_udo;
object->name = func_name;
object->pack = pack_name;
object->user = user;
return OG_SUCCESS;
}
* \brief Decode a sequence from raw data into an expr_node
*
*/
static void sr_decode_sequence(char *sr_data, uint32 temp_offset, variant_t *var)
{
uint32 offset = temp_offset;
var_seq_t *sequence = &var->v_seq;
sequence->user.len = *((uint32 *)(sr_data + offset));
offset += sizeof(uint32);
sequence->user.str = sr_data + offset;
offset += CM_ALIGN4(sequence->user.len);
sequence->name.len = *((uint32 *)(sr_data + offset));
offset += sizeof(uint32);
sequence->name.str = sr_data + offset;
offset += CM_ALIGN4(sequence->name.len);
sequence->mode = *(seq_mode_t *)(sr_data + offset);
var->type = OG_TYPE_BIGINT;
}
static status_t sr_decode_expr_tree(memory_context_t *mem_ctx, char *sr_data, uint32 offset, expr_tree_t **expr);
static status_t sr_decode_cond_tree(memory_context_t *mem_ctx, char *sr_data, uint32 offset, cond_tree_t **cond);
static status_t sr_decode_case_when(memory_context_t *mem_ctx, char *sr_data, uint32 offset, case_expr_t **case_expr);
status_t sr_decode_expr_node(memory_context_t *mem_ctx, char *sr_data, uint32 offset, expr_node_t **node)
{
if (offset == SR_NULL) {
*node = NULL;
return OG_SUCCESS;
}
sr_expr_node_t *sr_node = (sr_expr_node_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(expr_node_t), (void **)node));
(*node)->type = sr_node->type;
(*node)->datatype = sr_node->datatype;
(*node)->unary = sr_node->unary;
(*node)->format_json = sr_node->format_json;
(*node)->json_func_attr = sr_node->json_func_attr;
if ((*node)->type == EXPR_NODE_FUNC || (*node)->type == EXPR_NODE_USER_FUNC) {
OG_RETURN_IFERR(sr_decode_expr_tree(mem_ctx, sr_data, sr_node->args, &(*node)->argument));
}
switch ((*node)->type) {
case EXPR_NODE_RESERVED:
case EXPR_NODE_CONST:
OG_RETURN_IFERR(sr_decode_variant(sr_data, sr_node->value, &(*node)->value));
break;
case EXPR_NODE_SEQUENCE:
sr_decode_sequence(sr_data, sr_node->value, &(*node)->value);
break;
case EXPR_NODE_FUNC:
sr_decode_func(sr_data, sr_node->value, &(*node)->value);
if (IS_BUILDIN_FUNCTION(*node, ID_FUNC_ITEM_TRIM)) {
(*node)->ext_args = sr_node->ext_args;
}
if (IS_BUILDIN_FUNCTION(*node, ID_FUNC_ITEM_IF) || IS_BUILDIN_FUNCTION(*node, ID_FUNC_ITEM_LNNVL)) {
OG_RETURN_IFERR(sr_decode_cond_tree(mem_ctx, sr_data, sr_node->cond_arg, &((*node)->cond_arg)));
}
break;
case EXPR_NODE_USER_FUNC:
OG_RETURN_IFERR(sr_decode_user_func(mem_ctx, sr_data, sr_node->value, &(*node)->value));
break;
case EXPR_NODE_CASE:
OG_RETURN_IFERR(sr_decode_case_when(mem_ctx, sr_data, sr_node->value,
(case_expr_t **)VALUE_PTR(pointer_t, &(*node)->value)));
break;
case EXPR_NODE_ADD:
case EXPR_NODE_SUB:
case EXPR_NODE_MUL:
case EXPR_NODE_DIV:
case EXPR_NODE_MOD:
case EXPR_NODE_CAT:
case EXPR_NODE_BITAND:
case EXPR_NODE_BITOR:
case EXPR_NODE_BITXOR:
case EXPR_NODE_LSHIFT:
case EXPR_NODE_RSHIFT:
OG_RETURN_IFERR(sr_decode_expr_node(mem_ctx, sr_data, sr_node->left, &(*node)->left));
OG_RETURN_IFERR(sr_decode_expr_node(mem_ctx, sr_data, sr_node->right, &(*node)->right));
break;
case EXPR_NODE_NEGATIVE:
OG_RETURN_IFERR(sr_decode_expr_node(mem_ctx, sr_data, sr_node->right, &(*node)->right));
break;
#ifdef OG_RAC_ING
case EXPR_NODE_COLUMN:
case EXPR_NODE_DIRECT_COLUMN:
OG_RETURN_IFERR(sr_decode_column(sr_data, sr_node->value, &(*node)->value));
break;
case EXPR_NODE_STAR:
break;
#endif
default:
break;
}
return OG_SUCCESS;
}
static status_t sr_decode_expr_tree(memory_context_t *mem_ctx, char *sr_data, uint32 offset, expr_tree_t **expr)
{
if (offset == SR_NULL) {
*expr = NULL;
return OG_SUCCESS;
}
sr_expr_tree_t *sr_expr = (sr_expr_tree_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(expr_tree_t), (void **)expr));
OG_RETURN_IFERR(sr_decode_expr_node(mem_ctx, sr_data, sr_expr->root, &(*expr)->root));
return sr_decode_expr_tree(mem_ctx, sr_data, sr_expr->next, &(*expr)->next);
}
status_t sr_decode_expr(memory_context_t *mem_ctx, void *data, void **expr)
{
return sr_decode_expr_tree(mem_ctx, (char *)data, 0, (expr_tree_t **)expr);
}
status_t sr_decode_expr_list(memory_context_t *mem_ctx, void *data, uint32 offset, uint32 num, ...)
{
errno_t errcode = 0;
sr_list_t *sr_list = (sr_list_t *)data;
va_list list;
char *expr_data = NULL;
uint32 len;
status_t status = OG_SUCCESS;
va_start(list, num);
for (uint32 i = 0; i < num; i++) {
void **expr = va_arg(list, void **);
if (num == 1 || i == num - 1) {
len = offset - sr_list->cell[i];
} else {
len = sr_list->cell[i + 1] - sr_list->cell[i];
}
status = sr_alloc_mem(mem_ctx, len, (void **)&expr_data);
OG_BREAK_IF_TRUE(status != OG_SUCCESS);
if (len != 0) {
errcode = memcpy_s(expr_data, len, (char *)data + sr_list->cell[i], len);
if (errcode != EOK) {
OG_THROW_ERROR(ERR_SYSTEM_CALL, errcode);
status = OG_ERROR;
break;
}
}
status = sr_decode_expr(mem_ctx, (void *)expr_data, expr);
OG_BREAK_IF_TRUE(status != OG_SUCCESS);
}
va_end(list);
return status;
}
static status_t sr_decode_cmp_node(memory_context_t *mem_ctx, char *sr_data, uint32 offset, cmp_node_t **node)
{
if (offset == SR_NULL) {
*node = NULL;
return OG_SUCCESS;
}
sr_cmp_node_t *sr_cmp_node = (sr_cmp_node_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(cmp_node_t), (void **)node));
(*node)->join_type = sr_cmp_node->join_type;
(*node)->type = sr_cmp_node->type;
OG_RETURN_IFERR(sr_decode_expr_tree(mem_ctx, sr_data, sr_cmp_node->left, &(*node)->left));
return sr_decode_expr_tree(mem_ctx, sr_data, sr_cmp_node->right, &(*node)->right);
}
static status_t sr_decode_cond_node(memory_context_t *mem_ctx, char *sr_data, uint32 offset, cond_node_t **node)
{
if (offset == SR_NULL) {
*node = NULL;
return OG_SUCCESS;
}
sr_cond_node_t *sr_cond_node = (sr_cond_node_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(cond_node_t), (void **)node));
(*node)->type = sr_cond_node->type;
switch (sr_cond_node->type) {
case COND_NODE_COMPARE:
OG_RETURN_IFERR(sr_decode_cmp_node(mem_ctx, sr_data, sr_cond_node->cmp, &(*node)->cmp));
break;
case COND_NODE_TRUE:
case COND_NODE_FALSE:
break;
default:
OG_RETURN_IFERR(sr_decode_cond_node(mem_ctx, sr_data, sr_cond_node->left, &(*node)->left));
OG_RETURN_IFERR(sr_decode_cond_node(mem_ctx, sr_data, sr_cond_node->right, &(*node)->right));
break;
}
return OG_SUCCESS;
}
static status_t sr_decode_cond_tree(memory_context_t *mem_ctx, char *sr_data, uint32 offset, cond_tree_t **cond)
{
if (offset == SR_NULL) {
*cond = NULL;
return OG_SUCCESS;
}
sr_cond_tree_t *sr_cond = (sr_cond_tree_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(cond_tree_t), (void **)cond));
sql_init_cond_tree(mem_ctx, (*cond), (ga_alloc_func_t)sr_alloc_mem);
(*cond)->rownum_upper = sr_cond->rownum_upper;
(*cond)->loc = sr_cond->loc;
return sr_decode_cond_node(mem_ctx, sr_data, sr_cond->root, &(*cond)->root);
}
status_t sr_decode_cond(memory_context_t *context, void *data, void **expr)
{
return sr_decode_cond_tree(context, (char *)data, 0, (cond_tree_t **)expr);
}
static status_t sr_decode_simple_case_pair(memory_context_t *context, char *sr_data, uint32 offset, galist_t *list)
{
case_pair_t *pair = NULL;
if (offset == SR_NULL) {
list->count = 0;
return OG_SUCCESS;
}
sr_case_pair_t *sr_case_pair = (sr_case_pair_t *)(sr_data + offset);
OG_RETURN_IFERR(cm_galist_new(list, sizeof(case_pair_t), (void **)&pair));
OG_RETURN_IFERR(sr_decode_expr_tree(context, sr_data, sr_case_pair->when_expr, &pair->when_expr));
return sr_decode_expr_tree(context, sr_data, sr_case_pair->value, &pair->value);
}
static status_t sr_decode_searched_case_pair(memory_context_t *context, char *sr_data, uint32 offset, galist_t *list)
{
case_pair_t *pair = NULL;
if (offset == SR_NULL) {
list->count = 0;
return OG_SUCCESS;
}
sr_case_pair_t *sr_case_pair = (sr_case_pair_t *)(sr_data + offset);
OG_RETURN_IFERR(cm_galist_new(list, sizeof(case_pair_t), (void **)&pair));
OG_RETURN_IFERR(sr_decode_cond_tree(context, sr_data, sr_case_pair->when_cond, &pair->when_cond));
return sr_decode_expr_tree(context, sr_data, sr_case_pair->value, &pair->value);
}
static status_t sr_decode_case_when(memory_context_t *mem_ctx, char *sr_data, uint32 offset, case_expr_t **case_expr)
{
if (offset == SR_NULL) {
*case_expr = NULL;
return OG_SUCCESS;
}
sr_case_expr_t *sr_case_expr = (sr_case_expr_t *)(sr_data + offset);
OG_RETURN_IFERR(sr_alloc_mem(mem_ctx, sizeof(case_expr_t), (void **)case_expr));
(*case_expr)->is_cond = sr_case_expr->is_cond;
cm_galist_init(&(*case_expr)->pairs, (void *)mem_ctx, (ga_alloc_func_t)sr_alloc_mem);
if (!sr_case_expr->is_cond) {
OG_RETURN_IFERR(sr_decode_expr_tree(mem_ctx, sr_data, sr_case_expr->expr, &(*case_expr)->expr));
OG_RETURN_IFERR(
sr_decode_list(mem_ctx, sr_data, sr_case_expr->pairs, &(*case_expr)->pairs, sr_decode_simple_case_pair));
} else {
OG_RETURN_IFERR(
sr_decode_list(mem_ctx, sr_data, sr_case_expr->pairs, &(*case_expr)->pairs, sr_decode_searched_case_pair));
}
return sr_decode_expr_tree(mem_ctx, sr_data, sr_case_expr->default_expr, &(*case_expr)->default_expr);
}