* 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.
* -------------------------------------------------------------------------
*
* pl_procedure.c
*
*
* IDENTIFICATION
* src/ogsql/pl/meta/pl_procedure.c
*
* -------------------------------------------------------------------------
*/
#include "pl_procedure.h"
#include "srv_instance.h"
#include "pl_meta_common.h"
#ifdef OG_RAC_ING
status_t shd_pre_execute_ddl(sql_stmt_t *stmt, bool32 multi_ddl, bool32 need_encrypt);
status_t shd_trigger_check_for_rebalance(sql_stmt_t *stmt, text_t *user, text_t *tab);
#endif
static inline status_t pl_set_complex_type_arg_old(row_assist_t *ra, og_type_t dtype, plv_direction_t drct,
expr_tree_t *default_expr)
{
OG_RETURN_IFERR(row_put_int32(ra, dtype));
OG_RETURN_IFERR(row_put_int32(ra, (default_expr) ? 1 : 0));
OG_RETURN_IFERR(row_put_null(ra));
OG_RETURN_IFERR(row_put_null(ra));
OG_RETURN_IFERR(row_put_int32(ra, drct));
OG_RETURN_IFERR(row_put_null(ra));
OG_RETURN_IFERR(row_put_null(ra));
return row_put_null(ra);
}
#define SET_SCALAR_TYPE_ARG_RET_OLD(ra, ptypmd, drct, default_expr) \
do { \
OG_RETURN_IFERR(row_put_int32(ra, (int32)(ptypmd)->datatype)); \
OG_RETURN_IFERR(row_put_int32(ra, (default_expr) ? 1 : 0)); \
OG_RETURN_IFERR(row_put_null(ra)); \
OG_RETURN_IFERR(row_put_null(ra)); \
OG_RETURN_IFERR(row_put_int32(ra, drct)); \
OG_RETURN_IFERR(row_put_int32(ra, (int32)(ptypmd)->size)); \
row_put_prec_and_scale(ra, (uint32)(ptypmd)->datatype, (ptypmd)->precision, (ptypmd)->scale); \
} while (0)
static status_t pl_prepare_row_desc_old(row_assist_t *ra, pl_desc_t *desc, procedure_desc_t *proc_desc, plv_decl_t *arg,
uint32 pos, uint32 seq)
{
OG_RETURN_IFERR(row_put_int32(ra, (int32)desc->uid));
if (desc->type == PL_PACKAGE_SPEC) {
OG_RETURN_IFERR(row_put_str(ra, proc_desc->name));
} else {
OG_RETURN_IFERR(row_put_str(ra, desc->name));
}
if (pos == 0 && proc_desc->is_function) {
OG_RETURN_IFERR(row_put_null(ra));
} else {
OG_RETURN_IFERR(row_put_text(ra, &arg->name));
}
OG_RETURN_IFERR(row_put_int32(ra, (int32)pos));
OG_RETURN_IFERR(row_put_int32(ra, (int32)seq));
OG_RETURN_IFERR(row_put_int32(ra, 0));
switch (arg->type) {
case PLV_VAR:
SET_SCALAR_TYPE_ARG_RET_OLD(ra, &arg->variant.type, arg->drct, arg->default_expr);
break;
case PLV_ARRAY:
SET_SCALAR_TYPE_ARG_RET_OLD(ra, &arg->array.type, arg->drct, arg->default_expr);
break;
case PLV_CUR:
OG_RETURN_IFERR(pl_set_complex_type_arg_old(ra, OG_TYPE_CURSOR, arg->drct, arg->default_expr));
break;
case PLV_RECORD:
OG_RETURN_IFERR(pl_set_complex_type_arg_old(ra, OG_TYPE_RECORD, arg->drct, arg->default_expr));
break;
case PLV_OBJECT:
OG_RETURN_IFERR(pl_set_complex_type_arg_old(ra, OG_TYPE_OBJECT, arg->drct, arg->default_expr));
break;
case PLV_COLLECTION:
OG_RETURN_IFERR(pl_set_complex_type_arg_old(ra, OG_TYPE_COLLECTION, arg->drct, arg->default_expr));
break;
default:
return OG_ERROR;
}
OG_RETURN_IFERR(row_put_null(ra));
OG_RETURN_IFERR(row_put_null(ra));
if (desc->type == PL_PACKAGE_SPEC) {
OG_RETURN_IFERR(row_put_str(ra, desc->name));
} else {
OG_RETURN_IFERR(row_put_null(ra));
}
OG_RETURN_IFERR(row_put_int32(ra, (int32)proc_desc->proc_id));
OG_RETURN_IFERR(row_put_int32(ra, 0));
return OG_SUCCESS;
}
static status_t pl_write_sys_arguments(knl_session_t *knl_session, pl_desc_t *desc, procedure_desc_t *proc_desc)
{
row_assist_t ra;
galist_t *args = proc_desc->params;
uint32 arg_count = proc_desc->arg_count;
plv_decl_t *arg = NULL;
knl_cursor_t *cursor = NULL;
uint32 column_count;
uint32 pos;
uint32 seq;
if (args == NULL || args->count == 0) {
return OG_SUCCESS;
}
CM_SAVE_STACK(knl_session->stack);
if (sql_push_knl_cursor(knl_session, &cursor) != OG_SUCCESS) {
OG_THROW_ERROR(ERR_STACK_OVERFLOW);
CM_RESTORE_STACK(knl_session->stack);
return OG_ERROR;
}
knl_set_session_scn(knl_session, OG_INVALID_ID64);
knl_open_sys_cursor(knl_session, cursor, CURSOR_ACTION_INSERT, SYS_PROC_ARGS_ID, OG_INVALID_ID32);
column_count = knl_get_column_count(cursor->dc_entity);
seq = 1;
pos = 0;
for (uint32 id = 0; id < arg_count; id++) {
arg = (plv_decl_t *)cm_galist_get(args, id);
if (!(arg->type == PLV_CUR || arg->type == PLV_VAR || arg->type == PLV_ARRAY ||
CM_IS_PLV_UDT_DATATYPE(arg->type))) {
continue;
}
row_init(&ra, cursor->buf, g_instance->kernel.attr.max_row_size, column_count);
if (pl_prepare_row_desc_old(&ra, desc, proc_desc, arg, pos, seq) != OG_SUCCESS) {
CM_RESTORE_STACK(knl_session->stack);
return OG_ERROR;
}
pos++;
seq++;
if (knl_internal_insert(knl_session, cursor) != OG_SUCCESS) {
CM_RESTORE_STACK(knl_session->stack);
return OG_ERROR;
}
}
CM_RESTORE_STACK(knl_session->stack);
return OG_SUCCESS;
}
status_t pl_insert_proc_arg(knl_session_t *session, void *desc_in, void *pl_ctx_in)
{
pl_desc_t *desc = (pl_desc_t *)desc_in;
pl_entity_t *pl_ctx = (pl_entity_t *)pl_ctx_in;
procedure_desc_t *proc_desc = NULL;
procedure_t *proc = pl_ctx->procedure;
if (proc != NULL) {
proc_desc = &pl_ctx->procedure->desc;
proc_desc->oid = desc->oid;
OG_RETURN_IFERR(pl_write_sys_arguments(session, desc, proc_desc));
}
return OG_SUCCESS;
}
status_t pl_insert_package_proc_args(knl_session_t *session, void *desc_in, void *pl_ctx_in)
{
pl_desc_t *desc = (pl_desc_t *)desc_in;
pl_entity_t *pl_ctx = (pl_entity_t *)pl_ctx_in;
plv_decl_t *proc_decl = NULL;
package_spec_t *pack_def = NULL;
procedure_desc_t *proc_desc = NULL;
pack_def = pl_ctx->package_spec;
if (pack_def != NULL) {
for (uint32 id = 0; id < pack_def->defs->count; id++) {
proc_decl = (plv_decl_t *)cm_galist_get(pack_def->defs, id);
if (proc_decl->type == PLV_FUNCTION && proc_decl->func != NULL) {
proc_desc = &proc_decl->func->desc;
proc_desc->oid = desc->oid;
OG_RETURN_IFERR(pl_write_sys_arguments(session, desc, proc_desc));
}
}
}
return OG_SUCCESS;
}
status_t pl_delete_sys_argument(knl_session_t *session, void *desc_in)
{
pl_desc_t *desc = (pl_desc_t *)desc_in;
knl_cursor_t *cursor = NULL;
uint32 index_id;
knl_set_session_scn(session, OG_INVALID_ID64);
CM_SAVE_STACK(session->stack);
if (sql_push_knl_cursor(session, &cursor) != OG_SUCCESS) {
CM_RESTORE_STACK(session->stack);
return OG_ERROR;
}
index_id = (desc->type == PL_PACKAGE_SPEC) ? IX_PROCARGU_002_ID : IX_PROCARGU_001_ID;
knl_open_sys_cursor(session, cursor, CURSOR_ACTION_DELETE, SYS_PROC_ARGS_ID, index_id);
knl_init_index_scan(cursor, OG_FALSE);
knl_set_scan_key(INDEX_DESC(cursor->index), &cursor->scan_range.l_key, OG_TYPE_INTEGER, &desc->uid, sizeof(int32),
0);
knl_set_scan_key(INDEX_DESC(cursor->index), &cursor->scan_range.l_key, OG_TYPE_VARCHAR, desc->name,
(uint16)strlen(desc->name), 1);
knl_set_scan_key(INDEX_DESC(cursor->index), &cursor->scan_range.r_key, OG_TYPE_INTEGER, &desc->uid, sizeof(int32),
0);
knl_set_scan_key(INDEX_DESC(cursor->index), &cursor->scan_range.r_key, OG_TYPE_STRING, desc->name,
(uint16)strlen(desc->name), 1);
if (index_id == IX_PROCARGU_001_ID) {
knl_set_key_flag(&cursor->scan_range.l_key, SCAN_KEY_LEFT_INFINITE, IX_COL_PROCARGU_001_PACKAGE);
knl_set_key_flag(&cursor->scan_range.l_key, SCAN_KEY_LEFT_INFINITE, IX_COL_PROCARGU_001_SEQUENCE);
knl_set_key_flag(&cursor->scan_range.l_key, SCAN_KEY_LEFT_INFINITE, IX_COL_PROCARGU_001_OVERLOAD);
knl_set_key_flag(&cursor->scan_range.r_key, SCAN_KEY_RIGHT_INFINITE, IX_COL_PROCARGU_001_PACKAGE);
knl_set_key_flag(&cursor->scan_range.r_key, SCAN_KEY_RIGHT_INFINITE, IX_COL_PROCARGU_001_SEQUENCE);
knl_set_key_flag(&cursor->scan_range.r_key, SCAN_KEY_RIGHT_INFINITE, IX_COL_PROCARGU_001_OVERLOAD);
}
if (knl_fetch(session, cursor) != OG_SUCCESS) {
CM_RESTORE_STACK(session->stack);
return OG_ERROR;
}
while (!cursor->eof) {
if (knl_internal_delete(session, cursor) != OG_SUCCESS) {
CM_RESTORE_STACK(session->stack);
return OG_ERROR;
}
if (knl_fetch(session, cursor) != OG_SUCCESS) {
CM_RESTORE_STACK(session->stack);
return OG_ERROR;
}
}
CM_RESTORE_STACK(session->stack);
return OG_SUCCESS;
}
status_t pl_load_entity_update_proc_table(knl_session_t *session, void *desc_in, void *entity_in)
{
pl_desc_t *desc = (pl_desc_t *)desc_in;
pl_entity_t *entity = (pl_entity_t *)entity_in;
object_address_t obj_addr;
pl_entry_t *entry = entity->entry;
OG_RETURN_IFERR(pl_get_desc_objaddr(&obj_addr, desc));
OG_RETURN_IFERR(pl_update_sysproc_status(session, desc));
OG_RETURN_IFERR(pl_delete_sys_argument(session, desc));
OG_RETURN_IFERR(pl_delete_dependency(session, &obj_addr));
if (desc->status == OBJ_STATUS_VALID) {
OG_RETURN_IFERR(pl_insert_proc_arg(session, desc, entity));
OG_RETURN_IFERR(pl_insert_dependency_list(session, &obj_addr, &entity->ref_list));
}
if (entry->desc.status == OBJ_STATUS_VALID && desc->status != OBJ_STATUS_VALID) {
OG_RETURN_IFERR(pl_update_depender_status(session, &obj_addr));
}
return OG_SUCCESS;
}
static status_t pl_fetch_from_sysproc_by_name(knl_session_t *knl_session, knl_cursor_t *proc_cursor, text_t *user,
text_t *object)
{
uint32 uid;
knl_set_session_scn(knl_session, OG_INVALID_ID64);
if (!knl_get_user_id(knl_session, user, &uid)) {
OG_THROW_ERROR(ERR_USER_NOT_EXIST, T2S(user));
return OG_ERROR;
}
knl_open_sys_cursor(knl_session, proc_cursor, CURSOR_ACTION_SELECT, SYS_PROC_ID, 0);
knl_init_index_scan(proc_cursor, OG_FALSE);
knl_set_scan_key(INDEX_DESC(proc_cursor->index), &proc_cursor->scan_range.l_key, OG_TYPE_STRING, object->str,
object->len, IX_COL_PROC_001_NAME);
knl_set_scan_key(INDEX_DESC(proc_cursor->index), &proc_cursor->scan_range.l_key, OG_TYPE_INTEGER, &uid,
sizeof(int32), IX_COL_PROC_001_USER_ID);
knl_set_key_flag(&proc_cursor->scan_range.l_key, SCAN_KEY_LEFT_INFINITE, IX_COL_PROC_001_CLASS);
knl_set_scan_key(INDEX_DESC(proc_cursor->index), &proc_cursor->scan_range.r_key, OG_TYPE_STRING, object->str,
object->len, IX_COL_PROC_001_NAME);
knl_set_scan_key(INDEX_DESC(proc_cursor->index), &proc_cursor->scan_range.r_key, OG_TYPE_INTEGER, &uid,
sizeof(int32), IX_COL_PROC_001_USER_ID);
knl_set_key_flag(&proc_cursor->scan_range.r_key, SCAN_KEY_RIGHT_INFINITE, IX_COL_PROC_001_CLASS);
if (knl_fetch(knl_session, proc_cursor) != OG_SUCCESS) {
return OG_ERROR;
}
if (proc_cursor->eof) {
OG_THROW_ERROR(ERR_USER_OBJECT_NOT_EXISTS, "object", T2S(user), T2S_EX(object));
return OG_ERROR;
}
return OG_SUCCESS;
}
status_t pl_get_proc_id_by_name(sql_stmt_t *stmt, text_t *user, text_t *object, uint32 *uid, uint64 *oid)
{
knl_cursor_t *proc_cursor = NULL;
knl_session_t *knl_session = &stmt->session->knl_session;
OGSQL_SAVE_STACK(stmt);
if (sql_push_knl_cursor(knl_session, &proc_cursor) != OG_SUCCESS) {
OGSQL_RESTORE_STACK(stmt);
return OG_ERROR;
}
if (pl_fetch_from_sysproc_by_name(knl_session, proc_cursor, user, object) != OG_SUCCESS) {
OGSQL_RESTORE_STACK(stmt);
return OG_ERROR;
}
*uid = *(uint32 *)CURSOR_COLUMN_DATA(proc_cursor, SYS_PROC_USER_COL);
*oid = *(uint64 *)CURSOR_COLUMN_DATA(proc_cursor, SYS_PROC_OBJ_ID_COL);
OGSQL_RESTORE_STACK(stmt);
return OG_SUCCESS;
}