Skip to content

Commit

Permalink
Support sp_cursorprepare RPC call
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Kasko <[email protected]>
  • Loading branch information
staticlibs committed Jun 21, 2024
1 parent 99287cb commit b4b5c0b
Show file tree
Hide file tree
Showing 8 changed files with 420 additions and 46 deletions.
64 changes: 30 additions & 34 deletions contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2350,9 +2350,9 @@ static void
HandleSPCursorOpenCommon(TDSRequestSP req)
{
int curoptions = 0;
int ret,
i;
int ret;
StringInfoData buf;
char *paramdefstr;

TdsErrorContext->err_text = "Processing SP_CURSOROPEN Common Request";
/* fetch cursor options */
Expand Down Expand Up @@ -2395,24 +2395,18 @@ HandleSPCursorOpenCommon(TDSRequestSP req)
NULL /* TODO row_count */ , req->nTotalParams, req->boundParamsData, req->boundParamsNullList);
break;
case SP_CURSORPREPARE:
for (i = 0; i < buf.len-2; i++)
{
if ('@' == buf.data[i] && 'P' == buf.data[i + 1])
{
buf.data[i] = ' ';
buf.data[i + 1] = '$';
// todo: fixme for @P9+
buf.data[i + 2] = buf.data[i + 2] + 1;
}
}

set_ps_display("active");
activity = psprintf("SP_CURSORPREPARE: %s", buf.data);
pgstat_report_activity(STATE_RUNNING, activity);
pfree(activity);

if (req->dataParameter->isNull || req->metaDataParameterValue->len == 0)
paramdefstr = NULL;
else
paramdefstr = req->metaDataParameterValue->data;

ret = pltsql_plugin_handler_ptr->sp_cursorprepare_callback((int *) &req->cursorPreparedHandle, buf.data, curoptions, &req->scrollopt, &req->ccopt,
(int) req->nTotalBindParams, req->boundParamsOidList);
0, NULL, paramdefstr);
break;
case SP_CURSORPREPEXEC:
set_ps_display("active");
Expand Down Expand Up @@ -3345,9 +3339,9 @@ GetRPCRequest(StringInfo message)
case SP_CURSORPREPARE:
{
/*
* 1. Cursor prepared Handle parameter (mandatory) 2. query
* parameter (mandatory) 3. ExtraArg1 = scrollopt 4. ExtraArg2
* = ccopt
* 1. Cursor prepared Handle parameter OUT (mandatory) 2. parameters
* definition (mandatory) 3. query parameter (mandatory) 4. options
* (mandatory) 5. ExtraArg1 = scrollopt 6. ExtraArg2 = ccopt
*/
TDSInstrumentation(INSTR_UNSUPPORTED_TDS_SP_CURSORPREPARE);
if (unlikely(parameterCount < 4))
Expand All @@ -3361,27 +3355,33 @@ GetRPCRequest(StringInfo message)
errmsg("%s parameter should be of %s type", "Cursor prepared handle", "integer")));
request->cursorPreparedHandleParameter = request->parameter;

if (unlikely(!request->cursorPreparedHandleParameter->next))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("%s parameter is mandatory", "Parameters definition")));
if (unlikely(FetchDataTypeNameFromParameter(request->cursorPreparedHandleParameter->next) != TDS_TYPE_NVARCHAR &&
FetchDataTypeNameFromParameter(request->cursorPreparedHandleParameter->next) != TDS_TYPE_NCHAR &&
FetchDataTypeNameFromParameter(request->cursorPreparedHandleParameter->next) != TDS_TYPE_NTEXT))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s parameter should be of %s type", "Parameters definition", "NVARCHAR, NCHAR or NTEXT")));
request->dataParameter = request->cursorPreparedHandleParameter->next;

TdsReadUnicodeDataFromTokenCommon(message->data,
request->cursorPreparedHandleParameter->next,
request->dataParameter,
request->metaDataParameterValue);

if (unlikely(!request->cursorPreparedHandleParameter->next->next))
if (unlikely(!request->dataParameter->next))
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("%s parameter should not be null", "Query")));
if (unlikely(FetchDataTypeNameFromParameter(request->cursorPreparedHandleParameter->next->next) != TDS_TYPE_NVARCHAR &&
FetchDataTypeNameFromParameter(request->cursorPreparedHandleParameter->next->next) != TDS_TYPE_NTEXT))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s parameter should be of %s type", "Query", "NVARCHAR or NTEXT")));
request->queryParameter = request->cursorPreparedHandleParameter->next->next;

if (unlikely(FetchDataTypeNameFromParameter(request->queryParameter) != TDS_TYPE_NVARCHAR &&
FetchDataTypeNameFromParameter(request->parameter) != TDS_TYPE_NCHAR &&
FetchDataTypeNameFromParameter(request->parameter) != TDS_TYPE_NTEXT))
if (unlikely(FetchDataTypeNameFromParameter(request->dataParameter->next) != TDS_TYPE_NVARCHAR &&
FetchDataTypeNameFromParameter(request->dataParameter->next) != TDS_TYPE_NCHAR &&
FetchDataTypeNameFromParameter(request->dataParameter->next) != TDS_TYPE_NTEXT))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("%s parameter should be of %s type", "Query", "NVARCHAR or NTEXT")));
errmsg("%s parameter should be of %s type", "Query", "NVARCHAR, NCHAR or NTEXT")));
request->queryParameter = request->dataParameter->next;

request->cursorExtraArg1 = request->queryParameter->next;
if (unlikely(FetchDataTypeNameFromParameter(request->cursorExtraArg1) != TDS_TYPE_INTEGER))
Expand Down Expand Up @@ -3628,10 +3628,6 @@ ProcessRPCRequest(TDSRequest request)
HandleSPCursorOpenCommon(req);
break;
case SP_CURSORPREPARE:
// todo: fixme
req->boundParamsOidList = palloc0(sizeof(Oid) * 1);
req->boundParamsOidList[0] = 23;
req->nTotalBindParams = 1;
HandleSPCursorOpenCommon(req);
break;
case SP_CURSORFETCH:
Expand Down
28 changes: 24 additions & 4 deletions contrib/babelfishpg_tsql/src/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ void enable_sp_cursor_find_param_hook(void);
void disable_sp_cursor_find_param_hook(void);
void add_sp_cursor_param(char *name);
void reset_sp_cursor_params(void);
InlineCodeBlockArgs *create_args(int numargs);
void read_param_def(InlineCodeBlockArgs *args, const char *paramdefstr);

/* cursor information hashtab */
typedef struct cursorhashent
Expand Down Expand Up @@ -1099,11 +1101,29 @@ execute_sp_cursoropen_old(int *cursor_handle, const char *stmt, int *pscrollopt,
return execute_sp_cursoropen_common(NULL, cursor_handle, stmt, pscrollopt, pccopt, row_count, nparams, 0, NULL, values, nulls, true /* prepare */ , false /* save_plan */ , true /* execute */ );
}

/*
* Either nBindParams + boundParamsOidList or raw paramDef string can be passed by the caller.
*/
int
execute_sp_cursorprepare(int *stmt_handle, const char *stmt, int options, int *pscrollopt, int *pccopt, int nBindParams, Oid *boundParamsOidList)
execute_sp_cursorprepare(int *stmt_handle, const char *stmt, int options, int *pscrollopt, int *pccopt, int nBindParams, Oid *boundParamsOidList, const char* paramDef)
{
/* TODO: options handling */
return execute_sp_cursoropen_common(stmt_handle, NULL, stmt, pscrollopt, pccopt, NULL, 0, nBindParams, boundParamsOidList, NULL, NULL, true /* prepare */ , true /* save_plan */ , false /* execute */ );
InlineCodeBlockArgs *args;
int nBindParamsPass;
Oid *boundParamsOidListPass;

if (paramDef)
{
args = create_args(0);
read_param_def(args, paramDef);
nBindParamsPass = args->numargs;
boundParamsOidListPass = args->argtypes;
} else {
nBindParamsPass = nBindParams;
boundParamsOidListPass = boundParamsOidList;
}

return execute_sp_cursoropen_common(stmt_handle, NULL, stmt, pscrollopt, pccopt, NULL, 0, nBindParamsPass, boundParamsOidListPass, NULL, NULL, true /* prepare */ , true /* save_plan */ , false /* execute */ );
}

int
Expand Down Expand Up @@ -1300,10 +1320,10 @@ execute_sp_cursorfetch(int cursor_handle, int *pfetchtype, int *prownum, int *pn
*/
if (SPI_processed > 0)
fetch_info_rownum = portal->portalPos - SPI_processed + 1;
else if (portal->atStart)
fetch_info_rownum = 0;
else if (portal->atEnd)
fetch_info_rownum = -1;
else if (portal->atStart)
fetch_info_rownum = 0;
else
fetch_info_rownum = portal->portalPos + 1;

Expand Down
2 changes: 1 addition & 1 deletion contrib/babelfishpg_tsql/src/pl_exec-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1950,7 +1950,7 @@ exec_stmt_exec_sp(PLtsql_execstate *estate, PLtsql_stmt_exec_sp *stmt)
options,
(scrollopt_null ? NULL : &scrollopt),
(ccopt_null ? NULL : &ccopt),
args->numargs, args->argtypes);
args->numargs, args->argtypes, NULL);
}
PG_CATCH();
{
Expand Down
4 changes: 2 additions & 2 deletions contrib/babelfishpg_tsql/src/pltsql.h
Original file line number Diff line number Diff line change
Expand Up @@ -1698,7 +1698,7 @@ typedef struct PLtsql_protocol_plugin
int (*sp_cursoropen_callback) (int *cursor_handle, const char *stmt, int *scrollopt, int *ccopt,
int *row_count, int nparams, Datum *values, const char *nulls);
int (*sp_cursorprepare_callback) (int *stmt_handle, const char *stmt, int options, int *scrollopt, int *ccopt,
int nBindParams, Oid *boundParamsOidList);
int nBindParams, Oid *boundParamsOidList, const char* paramDef);
int (*sp_cursorexecute_callback) (int stmt_handle, int *cursor_handle, int *scrollopt, int *ccopt,
int *rowcount, int nparams, Datum *values, const char *nulls);
int (*sp_cursorprepexec_callback) (int *stmt_handle, int *cursor_handle, const char *stmt, int options, int *scrollopt, int *ccopt,
Expand Down Expand Up @@ -2165,7 +2165,7 @@ int execute_sp_cursor(int cursor_handle, int opttype, int rownum, const char *
int execute_sp_cursoropen_old(int *cursor_handle, const char *stmt, int *scrollopt, int *ccopt, int *row_count, int nparams, Datum *values, const char *nulls); /* old interface to be
* compatabile with TDS */
int execute_sp_cursoropen(int *cursor_handle, const char *stmt, int *scrollopt, int *ccopt, int *row_count, int nparams, int nBindParams, Oid *boundParamsOidList, Datum *values, const char *nulls);
int execute_sp_cursorprepare(int *stmt_handle, const char *stmt, int options, int *scrollopt, int *ccopt, int nBindParams, Oid *boundParamsOidList);
int execute_sp_cursorprepare(int *stmt_handle, const char *stmt, int options, int *scrollopt, int *ccopt, int nBindParams, Oid *boundParamsOidList, const char* paramDef);
int execute_sp_cursorexecute(int stmt_handle, int *cursor_handle, int *scrollopt, int *ccopt, int *rowcount, int nparams, Datum *values, const char *nulls);
int execute_sp_cursorprepexec(int *stmt_handle, int *cursor_handle, const char *stmt, int options, int *scrollopt, int *ccopt, int *row_count, int nparams, int nBindParams, Oid *boundParamsOidList, Datum *values, const char *nulls);
int execute_sp_cursorunprepare(int stmt_handle);
Expand Down
Loading

0 comments on commit b4b5c0b

Please sign in to comment.