1) Improve the implementation of *Disallow Premature* for
older versions of servers. 2) Implement SQLProcedures. Hiroshi Inoue
This commit is contained in:
parent
4f0e6e3345
commit
70b0831387
@ -994,7 +994,7 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
unsigned int declare_pos = 0;
|
unsigned int declare_pos = 0;
|
||||||
ConnectionClass *conn = SC_get_conn(stmt);
|
ConnectionClass *conn = SC_get_conn(stmt);
|
||||||
ConnInfo *ci = &(conn->connInfo);
|
ConnInfo *ci = &(conn->connInfo);
|
||||||
BOOL prepare_dummy_cursor = FALSE;
|
BOOL prepare_dummy_cursor = FALSE, begin_first = FALSE;
|
||||||
char token_save[32];
|
char token_save[32];
|
||||||
int token_len;
|
int token_len;
|
||||||
BOOL prev_token_end;
|
BOOL prev_token_end;
|
||||||
@ -1055,8 +1055,11 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
{
|
{
|
||||||
if (prepare_dummy_cursor)
|
if (prepare_dummy_cursor)
|
||||||
{
|
{
|
||||||
if (!CC_is_in_trans(conn))
|
if (!CC_is_in_trans(conn) && PG_VERSION_GE(conn, 7.1))
|
||||||
strcpy(new_statement, "begin;");
|
{
|
||||||
|
strcpy(new_statement, "BEGIN;");
|
||||||
|
begin_first = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (ci->drivers.use_declarefetch)
|
else if (ci->drivers.use_declarefetch)
|
||||||
SC_set_fetchcursor(stmt);
|
SC_set_fetchcursor(stmt);
|
||||||
@ -1718,8 +1721,8 @@ copy_statement_with_parameters(StatementClass *stmt)
|
|||||||
char fetchstr[128];
|
char fetchstr[128];
|
||||||
sprintf(fetchstr, ";fetch backward in %s;close %s;",
|
sprintf(fetchstr, ";fetch backward in %s;close %s;",
|
||||||
stmt->cursor_name, stmt->cursor_name);
|
stmt->cursor_name, stmt->cursor_name);
|
||||||
if (!CC_is_in_trans(conn))
|
if (begin_first && CC_is_in_autocommit(conn))
|
||||||
strcat(fetchstr, "commit;");
|
strcat(fetchstr, "COMMIT;");
|
||||||
CVT_APPEND_STR(fetchstr);
|
CVT_APPEND_STR(fetchstr);
|
||||||
stmt->inaccurate_result = TRUE;
|
stmt->inaccurate_result = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -349,10 +349,29 @@ PGAPI_Execute(
|
|||||||
if (SC_is_pre_executable(stmt))
|
if (SC_is_pre_executable(stmt))
|
||||||
{
|
{
|
||||||
BOOL in_trans = CC_is_in_trans(conn);
|
BOOL in_trans = CC_is_in_trans(conn);
|
||||||
|
BOOL issued_begin = FALSE, begin_included = FALSE;
|
||||||
QResultClass *res;
|
QResultClass *res;
|
||||||
|
|
||||||
|
if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
|
||||||
|
begin_included = TRUE;
|
||||||
|
else if (!in_trans)
|
||||||
|
{
|
||||||
|
res = CC_send_query(conn, "BEGIN", NULL);
|
||||||
|
if (res && !QR_aborted(res))
|
||||||
|
issued_begin = TRUE;
|
||||||
|
if (res)
|
||||||
|
QR_Destructor(res);
|
||||||
|
if (!issued_begin)
|
||||||
|
{
|
||||||
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
|
stmt->errormsg = "Handle prepare error";
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* we are now in a transaction */
|
||||||
CC_set_in_trans(conn);
|
CC_set_in_trans(conn);
|
||||||
stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
|
stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL);
|
||||||
if (res && QR_aborted(res))
|
if (!res || QR_aborted(res))
|
||||||
{
|
{
|
||||||
CC_abort(conn);
|
CC_abort(conn);
|
||||||
stmt->errornumber = STMT_EXEC_ERROR;
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
@ -361,8 +380,18 @@ PGAPI_Execute(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!in_trans)
|
if (CC_is_in_autocommit(conn))
|
||||||
|
{
|
||||||
|
if (issued_begin)
|
||||||
|
{
|
||||||
|
res = CC_send_query(conn, "COMMIT", NULL);
|
||||||
CC_set_no_trans(conn);
|
CC_set_no_trans(conn);
|
||||||
|
if (res)
|
||||||
|
QR_Destructor(res);
|
||||||
|
}
|
||||||
|
else if (!in_trans && begin_included)
|
||||||
|
CC_set_no_trans(conn);
|
||||||
|
}
|
||||||
stmt->status =STMT_FINISHED;
|
stmt->status =STMT_FINISHED;
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -650,6 +679,7 @@ PGAPI_ParamData(
|
|||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
ok = QR_command_successful(res);
|
ok = QR_command_successful(res);
|
||||||
|
CC_set_no_trans(stmt->hdbc);
|
||||||
QR_Destructor(res);
|
QR_Destructor(res);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
@ -658,8 +688,6 @@ PGAPI_ParamData(
|
|||||||
SC_log_error(func, "", stmt);
|
SC_log_error(func, "", stmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CC_set_no_trans(stmt->hdbc);
|
|
||||||
}
|
}
|
||||||
stmt->lobj_fd = -1;
|
stmt->lobj_fd = -1;
|
||||||
}
|
}
|
||||||
|
@ -832,7 +832,8 @@ PGAPI_GetFunctions(
|
|||||||
UWORD FAR *pfExists)
|
UWORD FAR *pfExists)
|
||||||
{
|
{
|
||||||
static char *func = "PGAPI_GetFunctions";
|
static char *func = "PGAPI_GetFunctions";
|
||||||
ConnInfo *ci = &(((ConnectionClass *)hdbc)->connInfo);
|
ConnectionClass *conn = (ConnectionClass *)hdbc;
|
||||||
|
ConnInfo *ci = &(conn->connInfo);
|
||||||
|
|
||||||
mylog("%s: entering...%u\n", func, fFunction);
|
mylog("%s: entering...%u\n", func, fFunction);
|
||||||
|
|
||||||
@ -915,7 +916,10 @@ PGAPI_GetFunctions(
|
|||||||
pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE;
|
pfExists[SQL_API_SQLPARAMOPTIONS] = FALSE;
|
||||||
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
|
pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
|
||||||
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
|
pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
|
||||||
|
if (PG_VERSION_LT(conn, 6.5))
|
||||||
pfExists[SQL_API_SQLPROCEDURES] = FALSE;
|
pfExists[SQL_API_SQLPROCEDURES] = FALSE;
|
||||||
|
else
|
||||||
|
pfExists[SQL_API_SQLPROCEDURES] = TRUE;
|
||||||
pfExists[SQL_API_SQLSETPOS] = TRUE;
|
pfExists[SQL_API_SQLSETPOS] = TRUE;
|
||||||
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
|
pfExists[SQL_API_SQLSETSCROLLOPTIONS] = TRUE; /* odbc 1.0 */
|
||||||
pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
|
pfExists[SQL_API_SQLTABLEPRIVILEGES] = FALSE;
|
||||||
@ -1090,7 +1094,10 @@ PGAPI_GetFunctions(
|
|||||||
*pfExists = FALSE;
|
*pfExists = FALSE;
|
||||||
break;
|
break;
|
||||||
case SQL_API_SQLPROCEDURES:
|
case SQL_API_SQLPROCEDURES:
|
||||||
|
if (PG_VERSION_LT(conn, 6.5))
|
||||||
*pfExists = FALSE;
|
*pfExists = FALSE;
|
||||||
|
else
|
||||||
|
*pfExists = TRUE;
|
||||||
break;
|
break;
|
||||||
case SQL_API_SQLSETPOS:
|
case SQL_API_SQLSETPOS:
|
||||||
*pfExists = TRUE;
|
*pfExists = TRUE;
|
||||||
@ -3615,31 +3622,54 @@ PGAPI_Procedures(
|
|||||||
{
|
{
|
||||||
static char *func = "PGAPI_Procedures";
|
static char *func = "PGAPI_Procedures";
|
||||||
StatementClass *stmt = (StatementClass *) hstmt;
|
StatementClass *stmt = (StatementClass *) hstmt;
|
||||||
Int2 result_cols;
|
ConnectionClass *conn = SC_get_conn(stmt);
|
||||||
|
char proc_query[INFO_INQUIRY_LEN];
|
||||||
|
QResultClass *res;
|
||||||
|
|
||||||
mylog("%s: entering...\n", func);
|
mylog("%s: entering...\n", func);
|
||||||
|
|
||||||
/*
|
if (PG_VERSION_LT(conn, 6.5))
|
||||||
* a statement is actually executed, so we'll have to do this
|
{
|
||||||
* ourselves.
|
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
|
||||||
*/
|
stmt->errormsg = "Version is too old";
|
||||||
result_cols = 8;
|
|
||||||
extend_bindings(stmt, result_cols);
|
|
||||||
|
|
||||||
/* set the field names */
|
|
||||||
QR_set_num_fields(stmt->result, result_cols);
|
|
||||||
QR_set_field_info(stmt->result, 0, "PROCEDURE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 1, "PROCEDURE_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 2, "PROCEDURE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 3, "NUM_INPUT_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 4, "NUM_OUTPUT_PARAMS", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 5, "NUM_RESULT_SET", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 6, "REMARKS", PG_TYPE_TEXT, MAX_INFO_STRING);
|
|
||||||
QR_set_field_info(stmt->result, 7, "PROCEDURE_TYPE", PG_TYPE_INT2, 2);
|
|
||||||
|
|
||||||
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
|
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
if (!SC_recycle_statement(stmt))
|
||||||
|
return SQL_ERROR;
|
||||||
|
/*
|
||||||
|
* The following seems the simplest implementation
|
||||||
|
*/
|
||||||
|
strcpy(proc_query, "select '' as ""PROCEDURE_CAT"", '' as ""PROCEDURE_SCHEM"","
|
||||||
|
" proname as ""PROCEDURE_NAME"", '' as ""NUM_INPUT_PARAMS"","
|
||||||
|
" '' as ""NUM_OUTPUT_PARAMS"", '' as ""NUM_RESULT_SETS"","
|
||||||
|
" '' as ""REMARKS"","
|
||||||
|
" case when prorettype =0 then 1::int2 else 2::int2 end as ""PROCEDURE_TYPE"" from pg_proc");
|
||||||
|
my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
|
||||||
|
|
||||||
|
res = CC_send_query(conn, proc_query, NULL);
|
||||||
|
if (!res || QR_aborted(res))
|
||||||
|
{
|
||||||
|
if (res)
|
||||||
|
QR_Destructor(res);
|
||||||
|
stmt->errornumber = STMT_EXEC_ERROR;
|
||||||
|
stmt->errormsg = "PGAPI_Procedures query error";
|
||||||
|
return SQL_ERROR;
|
||||||
|
}
|
||||||
|
stmt->result = res;
|
||||||
|
/*
|
||||||
|
* also, things need to think that this statement is finished so the
|
||||||
|
* results can be retrieved.
|
||||||
|
*/
|
||||||
|
stmt->status = STMT_FINISHED;
|
||||||
|
extend_bindings(stmt, 8);
|
||||||
|
/* set up the current tuple pointer for SQLFetch */
|
||||||
|
stmt->currTuple = -1;
|
||||||
|
stmt->rowset_start = -1;
|
||||||
|
stmt->current_col = -1;
|
||||||
|
|
||||||
|
return SQL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RETCODE SQL_API
|
RETCODE SQL_API
|
||||||
|
@ -468,10 +468,8 @@ SC_recycle_statement(StatementClass *self)
|
|||||||
conn = SC_get_conn(self);
|
conn = SC_get_conn(self);
|
||||||
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
|
||||||
{
|
{
|
||||||
QResultClass *res = CC_send_query(conn, "ABORT", NULL);
|
if (SC_is_pre_executable(self) && !conn->connInfo.disallow_premature)
|
||||||
|
CC_abort(conn);
|
||||||
QR_Destructor(res);
|
|
||||||
CC_set_no_trans(conn);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user