📄 statement.c
字号:
/*------- * Module: statement.c * * Description: This module contains functions related to creating * and manipulating a statement. * * Classes: StatementClass (Functions prefix: "SC_") * * API functions: SQLAllocStmt, SQLFreeStmt * * Comments: See "notice.txt" for copyright and license information. *------- */#ifndef _WIN32_WINNT#define _WIN32_WINNT 0x0400#endif /* _WIN32_WINNT */#include "statement.h"#include "bind.h"#include "connection.h"#include "multibyte.h"#include "qresult.h"#include "convert.h"#include "environ.h"#include <stdio.h>#include <string.h>#include <ctype.h>#include "pgapifunc.h"#define PRN_NULLCHECK/* Map sql commands to statement types */static struct{ int type; char *s;} Statement_Type[] ={ { STMT_TYPE_SELECT, "SELECT" } ,{ STMT_TYPE_INSERT, "INSERT" } ,{ STMT_TYPE_UPDATE, "UPDATE" } ,{ STMT_TYPE_DELETE, "DELETE" } ,{ STMT_TYPE_PROCCALL, "{" } ,{ STMT_TYPE_SET, "SET" } ,{ STMT_TYPE_RESET, "RESET" } ,{ STMT_TYPE_CREATE, "CREATE" } ,{ STMT_TYPE_DECLARE, "DECLARE" } ,{ STMT_TYPE_FETCH, "FETCH" } ,{ STMT_TYPE_MOVE, "MOVE" } ,{ STMT_TYPE_CLOSE, "CLOSE" } ,{ STMT_TYPE_PREPARE, "PREPARE" } ,{ STMT_TYPE_EXECUTE, "EXECUTE" } ,{ STMT_TYPE_DEALLOCATE, "DEALLOCATE" } ,{ STMT_TYPE_DROP, "DROP" } ,{ STMT_TYPE_START, "BEGIN" } ,{ STMT_TYPE_START, "START" } ,{ STMT_TYPE_TRANSACTION, "SAVEPOINT" } ,{ STMT_TYPE_TRANSACTION, "RELEASE" } ,{ STMT_TYPE_TRANSACTION, "COMMIT" } ,{ STMT_TYPE_TRANSACTION, "END" } ,{ STMT_TYPE_TRANSACTION, "ROLLBACK" } ,{ STMT_TYPE_TRANSACTION, "ABORT" } ,{ STMT_TYPE_LOCK, "LOCK" } ,{ STMT_TYPE_ALTER, "ALTER" } ,{ STMT_TYPE_GRANT, "GRANT" } ,{ STMT_TYPE_REVOKE, "REVOKE" } ,{ STMT_TYPE_COPY, "COPY" } ,{ STMT_TYPE_ANALYZE, "ANALYZE" } ,{ STMT_TYPE_NOTIFY, "NOTIFY" } ,{ STMT_TYPE_EXPLAIN, "EXPLAIN" } ,{ STMT_TYPE_SPECIAL, "VACUUM" } ,{ STMT_TYPE_SPECIAL, "REINDEX" } ,{ STMT_TYPE_SPECIAL, "CLUSTER" } ,{ STMT_TYPE_SPECIAL, "CHECKPOINT" } ,{ 0, NULL }};RETCODE SQL_APIPGAPI_AllocStmt(HDBC hdbc, HSTMT FAR * phstmt){ CSTR func = "PGAPI_AllocStmt"; ConnectionClass *conn = (ConnectionClass *) hdbc; StatementClass *stmt; ARDFields *ardopts; BindInfoClass *bookmark; mylog("%s: entering...\n", func); if (!conn) { CC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } stmt = SC_Constructor(conn); mylog("**** PGAPI_AllocStmt: hdbc = %p, stmt = %p\n", hdbc, stmt); if (!stmt) { CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory to allocate a further SQL-statement", func); *phstmt = SQL_NULL_HSTMT; return SQL_ERROR; } if (!CC_add_statement(conn, stmt)) { CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of statements exceeded.", func); SC_Destructor(stmt); *phstmt = SQL_NULL_HSTMT; return SQL_ERROR; } *phstmt = (HSTMT) stmt; /* Copy default statement options based from Connection options */ stmt->options = stmt->options_orig = conn->stmtOptions; stmt->ardi.ardopts = conn->ardOptions; ardopts = SC_get_ARDF(stmt); bookmark = ARD_AllocBookmark(ardopts); stmt->stmt_size_limit = CC_get_max_query_len(conn); /* Save the handle for later */ stmt->phstmt = phstmt; return SQL_SUCCESS;}RETCODE SQL_APIPGAPI_FreeStmt(HSTMT hstmt, SQLUSMALLINT fOption){ CSTR func = "PGAPI_FreeStmt"; StatementClass *stmt = (StatementClass *) hstmt; mylog("%s: entering...hstmt=%p, fOption=%hi\n", func, hstmt, fOption); if (!stmt) { SC_log_error(func, "", NULL); return SQL_INVALID_HANDLE; } SC_clear_error(stmt); if (fOption == SQL_DROP) { ConnectionClass *conn = stmt->hdbc; /* Remove the statement from the connection's statement list */ if (conn) { QResultClass *res; if (!CC_remove_statement(conn, stmt)) { SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.", func); return SQL_ERROR; /* stmt may be executing a * transaction */ } /* Free any cursors and discard any result info */ res = SC_get_Result(stmt); QR_Destructor(res); SC_init_Result(stmt); } if (stmt->execute_delegate) { PGAPI_FreeStmt(stmt->execute_delegate, SQL_DROP); stmt->execute_delegate = NULL; } if (stmt->execute_parent) stmt->execute_parent->execute_delegate = NULL; /* Destroy the statement and free any results, cursors, etc. */ SC_Destructor(stmt); } else if (fOption == SQL_UNBIND) SC_unbind_cols(stmt); else if (fOption == SQL_CLOSE) { /* * this should discard all the results, but leave the statement * itself in place (it can be executed again) */ stmt->transition_status = 0; if (stmt->execute_delegate) { PGAPI_FreeStmt(stmt->execute_delegate, SQL_DROP); stmt->execute_delegate = NULL; } if (!SC_recycle_statement(stmt)) { return SQL_ERROR; } } else if (fOption == SQL_RESET_PARAMS) SC_free_params(stmt, STMT_FREE_PARAMS_ALL); else { SC_set_error(stmt, STMT_OPTION_OUT_OF_RANGE_ERROR, "Invalid option passed to PGAPI_FreeStmt.", func); return SQL_ERROR; } return SQL_SUCCESS;}/* * StatementClass implementation */voidInitializeStatementOptions(StatementOptions *opt){ memset(opt, 0, sizeof(StatementOptions)); opt->maxRows = 0; /* driver returns all rows */ opt->maxLength = 0; /* driver returns all data for char/binary */ opt->keyset_size = 0; /* fully keyset driven is the default */ opt->scroll_concurrency = SQL_CONCUR_READ_ONLY; opt->cursor_type = SQL_CURSOR_FORWARD_ONLY; opt->retrieve_data = SQL_RD_ON; opt->use_bookmarks = SQL_UB_OFF;#if (ODBCVER >= 0x0300) opt->metadata_id = SQL_FALSE;#endif /* ODBCVER */}static void SC_clear_parse_status(StatementClass *self, ConnectionClass *conn){ self->parse_status = STMT_PARSE_NONE; if (PG_VERSION_LT(conn, 7.2)) { SC_set_checked_hasoids(self, TRUE); self->num_key_fields = PG_NUM_NORMAL_KEYS; }}static void SC_init_discard_output_params(StatementClass *self){ ConnectionClass *conn = SC_get_conn(self); if (!conn) return; self->discard_output_params = 0; if (!conn->connInfo.use_server_side_prepare) self->discard_output_params = 1;}static void SC_init_parse_method(StatementClass *self){ ConnectionClass *conn = SC_get_conn(self); self->parse_method = 0; if (!conn) return; if (self->catalog_result) return; if (conn->connInfo.drivers.parse) SC_set_parse_forced(self); if (self->multi_statement <= 0 && conn->connInfo.disallow_premature) SC_set_parse_tricky(self);}StatementClass *SC_Constructor(ConnectionClass *conn){ StatementClass *rv; rv = (StatementClass *) malloc(sizeof(StatementClass)); if (rv) { rv->hdbc = conn; rv->phstmt = NULL; rv->result = NULL; rv->curres = NULL; rv->catalog_result = FALSE; rv->prepare = NON_PREPARE_STATEMENT; rv->prepared = NOT_YET_PREPARED; rv->status = STMT_ALLOCATED; rv->internal = FALSE; rv->plan_name = NULL; rv->transition_status = 0; rv->multi_statement = -1; /* unknown */ rv->num_params = -1; /* unknown */ rv->__error_message = NULL; rv->__error_number = 0; rv->pgerror = NULL; rv->statement = NULL; rv->stmt_with_params = NULL; rv->load_statement = NULL; rv->execute_statement = NULL; rv->stmt_size_limit = -1; rv->statement_type = STMT_TYPE_UNKNOWN; rv->currTuple = -1; SC_set_rowset_start(rv, -1, FALSE); rv->current_col = -1; rv->bind_row = 0; rv->last_fetch_count = rv->last_fetch_count_include_ommitted = 0; rv->save_rowset_size = -1; rv->data_at_exec = -1; rv->current_exec_param = -1; rv->exec_start_row = -1; rv->exec_end_row = -1; rv->exec_current_row = -1; rv->put_data = FALSE; rv->ref_CC_error = FALSE; rv->lock_CC_for_rb = 0; rv->join_info = 0; SC_init_parse_method(rv); rv->lobj_fd = -1; INIT_NAME(rv->cursor_name); /* Parse Stuff */ rv->ti = NULL; rv->ntab = 0; rv->num_key_fields = -1; /* unknown */ SC_clear_parse_status(rv, conn); rv->proc_return = -1; SC_init_discard_output_params(rv); rv->cancel_info = 0; /* Clear Statement Options -- defaults will be set in AllocStmt */ memset(&rv->options, 0, sizeof(StatementOptions)); InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->ardi), rv, SQL_ATTR_APP_ROW_DESC); InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->apdi), rv, SQL_ATTR_APP_PARAM_DESC); InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->irdi), rv, SQL_ATTR_IMP_ROW_DESC); InitializeEmbeddedDescriptor((DescriptorClass *)&(rv->ipdi), rv, SQL_ATTR_IMP_PARAM_DESC); rv->pre_executing = FALSE; rv->inaccurate_result = FALSE; rv->miscinfo = 0; rv->rbonerr = 0; rv->updatable = FALSE; rv->diag_row_count = 0; rv->stmt_time = 0; rv->execute_delegate = NULL; rv->execute_parent = NULL; rv->allocated_callbacks = 0; rv->num_callbacks = 0; rv->callbacks = NULL; GetDataInfoInitialize(SC_get_GDTI(rv)); PutDataInfoInitialize(SC_get_PDTI(rv)); INIT_STMT_CS(rv); } return rv;}charSC_Destructor(StatementClass *self){ CSTR func = "SC_Destrcutor"; QResultClass *res = SC_get_Result(self); if (!self) return FALSE; mylog("SC_Destructor: self=%p, self->result=%p, self->hdbc=%p\n", self, res, self->hdbc); SC_clear_error(self); if (STMT_EXECUTING == self->status) { SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.", func); return FALSE; } if (res) { if (!self->hdbc) res->conn = NULL; /* prevent any dbase activity */ QR_Destructor(res); } SC_initialize_stmts(self, TRUE); /* Free the parsed table information */ SC_initialize_cols_info(self, FALSE, TRUE); NULL_THE_NAME(self->cursor_name); /* Free the parsed field information */ DC_Destructor((DescriptorClass *) SC_get_ARDi(self)); DC_Destructor((DescriptorClass *) SC_get_APDi(self)); DC_Destructor((DescriptorClass *) SC_get_IRDi(self)); DC_Destructor((DescriptorClass *) SC_get_IPDi(self)); GDATA_unbind_cols(SC_get_GDTI(self), TRUE); PDATA_free_params(SC_get_PDTI(self), STMT_FREE_PARAMS_ALL); if (self->__error_message) free(self->__error_message); if (self->pgerror) ER_Destructor(self->pgerror); cancelNeedDataState(self); if (self->callbacks) free(self->callbacks); DELETE_STMT_CS(self); free(self); mylog("SC_Destructor: EXIT\n"); return TRUE;}/* * Free parameters and free the memory from the * data-at-execution parameters that was allocated in SQLPutData. */voidSC_free_params(StatementClass *self, char option){ if (option != STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY) { APD_free_params(SC_get_APDF(self), option); IPD_free_params(SC_get_IPDF(self), option); } PDATA_free_params(SC_get_PDTI(self), option); self->data_at_exec = -1; self->current_exec_param = -1; self->put_data = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -