Commit 70b08313 authored by Hiroshi Inoue's avatar Hiroshi Inoue

1) Improve the implementation of *Disallow Premature* for

   older versions of servers.
2) Implement SQLProcedures.

Hiroshi Inoue
parent 4f0e6e33
...@@ -994,7 +994,7 @@ copy_statement_with_parameters(StatementClass *stmt) ...@@ -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) ...@@ -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) ...@@ -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( ...@@ -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( ...@@ -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);
if (res)
QR_Destructor(res);
}
else if (!in_trans && begin_included)
CC_set_no_trans(conn); 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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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( ...@@ -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,30 +3622,53 @@ PGAPI_Procedures( ...@@ -3615,30 +3622,53 @@ 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))
{
stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
stmt->errormsg = "Version is too old";
SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
return SQL_ERROR;
}
if (!SC_recycle_statement(stmt))
return SQL_ERROR;
/* /*
* a statement is actually executed, so we'll have to do this * The following seems the simplest implementation
* ourselves.
*/ */
result_cols = 8; strcpy(proc_query, "select '' as ""PROCEDURE_CAT"", '' as ""PROCEDURE_SCHEM"","
extend_bindings(stmt, result_cols); " proname as ""PROCEDURE_NAME"", '' as ""NUM_INPUT_PARAMS"","
" '' as ""NUM_OUTPUT_PARAMS"", '' as ""NUM_RESULT_SETS"","
/* set the field names */ " '' as ""REMARKS"","
QR_set_num_fields(stmt->result, result_cols); " case when prorettype =0 then 1::int2 else 2::int2 end as ""PROCEDURE_TYPE"" from pg_proc");
QR_set_field_info(stmt->result, 0, "PROCEDURE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING); my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
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); 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; 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;
} }
......
...@@ -468,10 +468,8 @@ SC_recycle_statement(StatementClass *self) ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment