Skip to content

Commit

Permalink
fix insert exec with type cast (#2017)
Browse files Browse the repository at this point in the history
Previously insert exec implement didn't consider the type cast during execution, this fix has add a implicit type cast between insert execution and exec execution if the type is mismatched.

Engine pr : babelfish-for-postgresql/postgresql_modified_for_babelfish#256

Task: BABEL-2999, BABEL-4426
Signed-off-by: Zhibai Song <szh@amazon.com>
  • Loading branch information
forestkeeper committed Nov 15, 2023
1 parent 3c4666e commit 2d20e6c
Show file tree
Hide file tree
Showing 28 changed files with 520 additions and 5 deletions.
13 changes: 13 additions & 0 deletions contrib/babelfishpg_tsql/src/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ static bool plsql_TriggerRecursiveCheck(ResultRelInfo *resultRelInfo);
static bool bbf_check_rowcount_hook(int es_processed);

static char *get_local_schema_for_bbf_functions(Oid proc_nsp_oid);
extern bool called_from_tsql_insert_exec();
extern Datum pltsql_exec_tsql_cast_value(Datum value, bool *isnull,
Oid valtype, int32 valtypmod,
Oid reqtype, int32 reqtypmod);

/*****************************************
* Replication Hooks
Expand Down Expand Up @@ -231,6 +235,8 @@ static set_local_schema_for_func_hook_type prev_set_local_schema_for_func_hook =
static bbf_get_sysadmin_oid_hook_type prev_bbf_get_sysadmin_oid_hook = NULL;
/* TODO: do we need to use variable to store hook value before transfrom pivot? No other function uses the same hook, should be redundant */
static transform_pivot_clause_hook_type pre_transform_pivot_clause_hook = NULL;
static called_from_tsql_insert_exec_hook_type pre_called_from_tsql_insert_exec_hook = NULL;
static exec_tsql_cast_value_hook_type pre_exec_tsql_cast_value_hook = NULL;

/*****************************************
* Install / Uninstall
Expand Down Expand Up @@ -396,6 +402,12 @@ InstallExtendedHooks(void)

prev_optimize_explicit_cast_hook = optimize_explicit_cast_hook;
optimize_explicit_cast_hook = optimize_explicit_cast;

pre_called_from_tsql_insert_exec_hook = called_from_tsql_insert_exec_hook;
called_from_tsql_insert_exec_hook = called_from_tsql_insert_exec;

pre_exec_tsql_cast_value_hook = exec_tsql_cast_value_hook;
exec_tsql_cast_value_hook = pltsql_exec_tsql_cast_value;
}

void
Expand Down Expand Up @@ -459,6 +471,7 @@ UninstallExtendedHooks(void)
bbf_get_sysadmin_oid_hook = prev_bbf_get_sysadmin_oid_hook;
transform_pivot_clause_hook = pre_transform_pivot_clause_hook;
optimize_explicit_cast_hook = prev_optimize_explicit_cast_hook;
called_from_tsql_insert_exec_hook = pre_called_from_tsql_insert_exec_hook;
}

/*****************************************
Expand Down
22 changes: 18 additions & 4 deletions contrib/babelfishpg_tsql/src/pl_exec-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#include "funcapi.h"

#include "access/table.h"
#include "access/attmap.h"
#include "catalog/namespace.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_language.h"
#include "commands/proclang.h"
#include "executor/tstoreReceiver.h"
Expand Down Expand Up @@ -65,6 +67,7 @@ static bool is_char_identstart(char c);
static bool is_char_identpart(char c);

void read_param_def(InlineCodeBlockArgs *args, const char *paramdefstr);
bool called_from_tsql_insert_exec(void);
void cache_inline_args(PLtsql_function *func, InlineCodeBlockArgs *args);
InlineCodeBlockArgs *create_args(int numargs);
InlineCodeBlockArgs *clone_inline_args(InlineCodeBlockArgs *args);
Expand Down Expand Up @@ -104,6 +107,7 @@ extern SPIPlanPtr prepare_stmt_exec(PLtsql_execstate *estate, PLtsql_function *f
extern int sp_prepare_count;

BulkCopyStmt *cstmt = NULL;
bool called_from_tsql_insert_execute = false;

int insert_bulk_rows_per_batch = DEFAULT_INSERT_BULK_ROWS_PER_BATCH;
int insert_bulk_kilobytes_per_batch = DEFAULT_INSERT_BULK_PACKET_SIZE;
Expand All @@ -115,7 +119,7 @@ static bool prev_insert_bulk_keep_nulls = false;

/* return a underlying node if n is implicit casting and underlying node is a certain type of node */
static Node *get_underlying_node_from_implicit_casting(Node *n, NodeTag underlying_nodetype);

/*
* The pltsql_proc_return_code global variable is used to record the
* return code (RETURN 41 + 1) of the most recently completed procedure
Expand Down Expand Up @@ -2987,6 +2991,13 @@ exec_stmt_grantdb(PLtsql_execstate *estate, PLtsql_stmt_grantdb *stmt)
return PLTSQL_RC_OK;
}

bool called_from_tsql_insert_exec()
{
if (sql_dialect != SQL_DIALECT_TSQL)
return false;
return called_from_tsql_insert_execute;
}

/*
* For naked SELECT stmt in INSERT ... EXECUTE, instead of pushing the result to
* the client, we accumulate the result in estate->tuple_store (similar to
Expand All @@ -3010,10 +3021,11 @@ exec_stmt_insert_execute_select(PLtsql_execstate *estate, PLtsql_expr *query)
/* Use eval_mcontext for tuple conversion work */
oldcontext = MemoryContextSwitchTo(get_eval_mcontext(estate));

called_from_tsql_insert_execute = true;
tupmap = convert_tuples_by_position(portal->tupDesc,
estate->tuple_store_desc,
gettext_noop("structure of query does not match function result type"));

called_from_tsql_insert_execute = false;
while (true)
{
uint64 i;
Expand All @@ -3031,7 +3043,11 @@ exec_stmt_insert_execute_select(PLtsql_execstate *estate, PLtsql_expr *query)
HeapTuple tuple = SPI_tuptable->vals[i];

if (tupmap)
{
called_from_tsql_insert_execute = true;
tuple = execute_attr_map_tuple(tuple, tupmap);
called_from_tsql_insert_execute = false;
}
tuplestore_puttuple(estate->tuple_store, tuple);
if (tupmap)
heap_freetuple(tuple);
Expand Down Expand Up @@ -3121,7 +3137,6 @@ exec_stmt_insert_bulk(PLtsql_execstate *estate, PLtsql_stmt_insert_bulk *stmt)
return PLTSQL_RC_OK;
}


int exec_stmt_dbcc(PLtsql_execstate *estate, PLtsql_stmt_dbcc *stmt)
{
switch (stmt->dbcc_stmt_type)
Expand All @@ -3135,7 +3150,6 @@ int exec_stmt_dbcc(PLtsql_execstate *estate, PLtsql_stmt_dbcc *stmt)
return PLTSQL_RC_OK;
}


void exec_stmt_dbcc_checkident(PLtsql_stmt_dbcc *stmt)
{
struct dbcc_checkident dbcc_stmt = stmt->dbcc_stmt_data.dbcc_checkident;
Expand Down
14 changes: 13 additions & 1 deletion contrib/babelfishpg_tsql/src/pl_exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ static Datum exec_cast_value(PLtsql_execstate *estate,
Datum value, bool *isnull,
Oid valtype, int32 valtypmod,
Oid reqtype, int32 reqtypmod);
Datum pltsql_exec_tsql_cast_value(Datum value, bool *isnull,
Oid valtype, int32 valtypmod,
Oid reqtype, int32 reqtypmod);
static pltsql_CastHashEntry *get_cast_hashentry(PLtsql_execstate *estate,
Oid srctype, int32 srctypmod,
Oid dsttype, int32 dsttypmod);
Expand Down Expand Up @@ -4347,7 +4350,6 @@ pltsql_estate_setup(PLtsql_execstate *estate,
estate->insert_exec = (func->fn_prokind == PROKIND_PROCEDURE ||
strcmp(func->fn_signature, "inline_code_block") == 0)
&& rsi;

estate->pivot_number = 0;
estate->pivot_parsetree_list = NIL;

Expand Down Expand Up @@ -10385,3 +10387,13 @@ get_original_query_string(void)
{
return original_query_string;
}

Datum pltsql_exec_tsql_cast_value(Datum value, bool *isnull,
Oid valtype, int32 valtypmod,
Oid reqtype, int32 reqtypmod)
{
return exec_cast_value(get_current_tsql_estate(),
value, isnull,
valtype, valtypmod,
reqtype, reqtypmod);
}
2 changes: 2 additions & 0 deletions contrib/babelfishpg_tsql/src/pl_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -4790,6 +4790,7 @@ pltsql_inline_handler(PG_FUNCTION_ARGS)
rsinfo.isDone = ExprSingleResult;
rsinfo.setResult = NULL;
rsinfo.setDesc = NULL;
ReleaseTupleDesc(reldesc);
}

/* And run the function */
Expand Down Expand Up @@ -4856,6 +4857,7 @@ pltsql_inline_handler(PG_FUNCTION_ARGS)
dest->receiveSlot(slot, dest);
ExecClearTuple(slot);
}
ReleaseTupleDesc(rsinfo.expectedDesc);
ExecDropSingleTupleTableSlot(slot);
}

Expand Down
29 changes: 29 additions & 0 deletions test/JDBC/expected/BABEL-2999-vu-cleanup.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
drop table if exists t2_BABEL2999;
GO

drop table t1_BABEL2999;
GO

drop table t3_BABEL2999;
GO

drop table t3_BABEL2999_2;
GO

drop procedure p1_BABEL2999;
GO

drop procedure p2_BABEL2999
GO

drop procedure p3_BABEL2999
GO

drop table t4_BABEL2999;
GO

drop table t5_BABEL2999;
GO

drop table t6_BABEL2999
GO
32 changes: 32 additions & 0 deletions test/JDBC/expected/BABEL-2999-vu-prepare.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
drop table if exists t1_BABEL2999;
GO

create table t1_BABEL2999(b varchar(10));
GO

create table t2_BABEL2999(b int);
GO

create table t3_BABEL2999(b varchar);
GO

create procedure p1_BABEL2999 as select 'abc';
GO

create procedure p2_BABEL2999 as select 555;
GO

create table t3_BABEL2999_2(a int, b datetime, c varchar(20))
GO

create procedure p3_BABEL2999 as select '123', 123, 123;
GO

create table t4_BABEL2999( a binary(30), b varbinary(30), c varchar(30), d datetime, e smalldatetime)
GO

create table t5_BABEL2999( a decimal, b numeric)
GO

create table t6_BABEL2999( a int, b tinyint, c smallint)
GO
Loading

0 comments on commit 2d20e6c

Please sign in to comment.