📄 statement.c
字号:
if (option == STMT_FREE_PARAMS_ALL) { self->exec_start_row = -1; self->exec_end_row = -1; self->exec_current_row = -1; }}intstatement_type(const char *statement){ int i; /* ignore leading whitespace in query string */ while (*statement && (isspace((UCHAR) *statement) || *statement == '(')) statement++; for (i = 0; Statement_Type[i].s; i++) if (!strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s))) return Statement_Type[i].type; return STMT_TYPE_OTHER;}voidSC_set_planname(StatementClass *stmt, const char *plan_name){ if (stmt->plan_name) free(stmt->plan_name); if (plan_name && plan_name[0]) stmt->plan_name = strdup(plan_name); else stmt->plan_name = NULL;}voidSC_set_rowset_start(StatementClass *stmt, SQLLEN start, BOOL valid_base){ QResultClass *res = SC_get_Curres(stmt); SQLLEN incr = start - stmt->rowset_start;inolog("%p->SC_set_rowstart " FORMAT_LEN "->" FORMAT_LEN "(%s) ", stmt, stmt->rowset_start, start, valid_base ? "valid" : "unknown"); if (res != NULL) { BOOL valid = QR_has_valid_base(res);inolog(":QR is %s", QR_has_valid_base(res) ? "valid" : "unknown"); if (valid) { if (valid_base) QR_inc_rowstart_in_cache(res, incr); else QR_set_no_valid_base(res); } else if (valid_base) { QR_set_has_valid_base(res); if (start < 0) QR_set_rowstart_in_cache(res, -1); else QR_set_rowstart_in_cache(res, 0); } if (!QR_get_cursor(res)) res->key_base = start;inolog(":QR result=" FORMAT_LEN "(%s)", QR_get_rowstart_in_cache(res), QR_has_valid_base(res) ? "valid" : "unknown"); } stmt->rowset_start = start;inolog(":stmt result=" FORMAT_LEN "\n", stmt->rowset_start);}voidSC_inc_rowset_start(StatementClass *stmt, SQLLEN inc){ SQLLEN start = stmt->rowset_start + inc; SC_set_rowset_start(stmt, start, TRUE);}intSC_set_current_col(StatementClass *stmt, int col){ if (col == stmt->current_col) return col; if (col >= 0) reset_a_getdata_info(SC_get_GDTI(stmt), col + 1); stmt->current_col = col; return stmt->current_col;}voidSC_set_prepared(StatementClass *stmt, BOOL prepared){ if (prepared == stmt->prepared) ; else if (NOT_YET_PREPARED == prepared && PREPARED_PERMANENTLY == stmt->prepared) { ConnectionClass *conn = SC_get_conn(stmt); if (conn && CONN_CONNECTED == conn->status) { if (CC_is_in_error_trans(conn)) { CC_mark_a_object_to_discard(conn, 's', stmt->plan_name); } else { QResultClass *res; char dealloc_stmt[128]; sprintf(dealloc_stmt, "DEALLOCATE \"%s\"", stmt->plan_name); res = CC_send_query(conn, dealloc_stmt, NULL, IGNORE_ABORT_ON_CONN | ROLLBACK_ON_ERROR, NULL); QR_Destructor(res); } } } if (NOT_YET_PREPARED == prepared) SC_set_planname(stmt, NULL); stmt->prepared = prepared;}/* * Initialize stmt_with_params, load_statement and execute_statement * member pointer deallocating corresponding prepared plan. * Also initialize statement member pointer if specified. */RETCODESC_initialize_stmts(StatementClass *self, BOOL initializeOriginal){ ConnectionClass *conn = SC_get_conn(self); if (self->lock_CC_for_rb > 0) { while (self->lock_CC_for_rb > 0) { LEAVE_CONN_CS(conn); self->lock_CC_for_rb--; } } if (initializeOriginal) { if (self->statement) { free(self->statement); self->statement = NULL; } if (self->execute_statement) { free(self->execute_statement); self->execute_statement = NULL; } self->prepare = NON_PREPARE_STATEMENT; SC_set_prepared(self, NOT_YET_PREPARED); self->statement_type = STMT_TYPE_UNKNOWN; /* unknown */ self->multi_statement = -1; /* unknown */ self->num_params = -1; /* unknown */ self->proc_return = -1; /* unknown */ self->join_info = 0; SC_init_parse_method(self); SC_init_discard_output_params(self); } if (self->stmt_with_params) { free(self->stmt_with_params); self->stmt_with_params = NULL; } if (self->load_statement) { free(self->load_statement); self->load_statement = NULL; } return 0;}BOOL SC_opencheck(StatementClass *self, const char *func){ QResultClass *res; if (!self) return FALSE; if (self->status == STMT_EXECUTING) { SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.", func); return TRUE; } /* * We can dispose the result of PREMATURE execution any time. */ if (self->prepare && self->status == STMT_PREMATURE) { mylog("SC_opencheck: self->prepare && self->status == STMT_PREMATURE\n"); return FALSE; } if (res = SC_get_Curres(self), NULL != res) { if (QR_command_maybe_successful(res) && res->backend_tuples) { SC_set_error(self, STMT_SEQUENCE_ERROR, "The cursor is open.", func); return TRUE; } } return FALSE;}RETCODESC_initialize_and_recycle(StatementClass *self){ SC_initialize_stmts(self, TRUE); if (!SC_recycle_statement(self)) return SQL_ERROR; return SQL_SUCCESS;}/* * Called from SQLPrepare if STMT_PREMATURE, or * from SQLExecute if STMT_FINISHED, or * from SQLFreeStmt(SQL_CLOSE) */charSC_recycle_statement(StatementClass *self){ CSTR func = "SC_recycle_statement"; ConnectionClass *conn; QResultClass *res; mylog("%s: self= %p\n", func, self); SC_clear_error(self); /* This would not happen */ if (self->status == STMT_EXECUTING) { SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.", func); return FALSE; } conn = SC_get_conn(self); switch (self->status) { case STMT_ALLOCATED: /* this statement does not need to be recycled */ return TRUE; case STMT_READY: break; case STMT_PREMATURE: /* * Premature execution of the statement might have caused the * start of a transaction. If so, we have to rollback that * transaction. */ if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) { if (SC_is_pre_executable(self) && !SC_is_parse_tricky(self)) CC_abort(conn); } break; case STMT_FINISHED: break; default: SC_set_error(self, STMT_INTERNAL_ERROR, "An internal error occured while recycling statements", func); return FALSE; } switch (self->prepared) { case NOT_YET_PREPARED: case ONCE_DESCRIBED: /* Free the parsed table/field information */ SC_initialize_cols_info(self, TRUE, TRUE);inolog("SC_clear_parse_status\n"); SC_clear_parse_status(self, conn); break; } /* Free any cursors */ if (res = SC_get_Result(self), res) { if (PREPARED_PERMANENTLY == self->prepared) QR_close_result(res, FALSE); else { QR_Destructor(res); SC_init_Result(self); } } self->inaccurate_result = FALSE; self->miscinfo = 0; /* self->rbonerr = 0; Never clear the bits here */ /* * Reset only parameters that have anything to do with results */ self->status = STMT_READY; self->catalog_result = FALSE; /* not very important */ self->currTuple = -1; SC_set_rowset_start(self, -1, FALSE); SC_set_current_col(self, -1); self->bind_row = 0;inolog("%s statement=%p ommitted=0\n", func, self); self->last_fetch_count = self->last_fetch_count_include_ommitted = 0; self->__error_message = NULL; self->__error_number = 0; self->lobj_fd = -1; /* * Free any data at exec params before the statement is executed * again. If not, then there will be a memory leak when the next * SQLParamData/SQLPutData is called. */ SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY); SC_initialize_stmts(self, FALSE); cancelNeedDataState(self); self->cancel_info = 0; /* * reset the current attr setting to the original one. */ self->options.scroll_concurrency = self->options_orig.scroll_concurrency; self->options.cursor_type = self->options_orig.cursor_type; self->options.keyset_size = self->options_orig.keyset_size; self->options.maxLength = self->options_orig.maxLength; self->options.maxRows = self->options_orig.maxRows; return TRUE;}/* * Scan the query wholly or partially (if specifed next_cmd). * Also count the number of parameters respectviely. */voidSC_scanQueryAndCountParams(const char *query, const ConnectionClass *conn, Int4 *next_cmd, SQLSMALLINT * pcpar, char *multi_st, char *proc_return){ CSTR func = "SC_scanQueryAndCountParams"; char literal_quote = LITERAL_QUOTE, identifier_quote = IDENTIFIER_QUOTE, dollar_quote = DOLLAR_QUOTE; const char *sptr, *tstr, *tag = NULL; size_t taglen = 0; char tchar, bchar, escape_in_literal = '\0'; char in_literal = FALSE, in_identifier = FALSE, in_dollar_quote = FALSE, in_escape = FALSE, del_found = FALSE, multi = FALSE; SQLSMALLINT num_p; encoded_str encstr; mylog("%s: entering...\n", func); num_p = 0; if (proc_return) *proc_return = 0; if (next_cmd) *next_cmd = -1; tstr = query; make_encoded_str(&encstr, conn, tstr); for (sptr = tstr, bchar = '\0'; *sptr; sptr++) { tchar = encoded_nextchar(&encstr); if (ENCODE_STATUS(encstr) != 0) /* multibyte char */ { if ((UCHAR) tchar >= 0x80) bchar = tchar; continue; } if (!multi && del_found) { if (!isspace(tchar)) { multi = TRUE; if (next_cmd) break; } } if (in_dollar_quote) { if (tchar == dollar_quote) { if (strncmp(sptr, tag, taglen) == 0) { in_dollar_quote = FALSE; tag = NULL; sptr += taglen; sptr--; encoded_position_shift(&encstr, taglen - 1); } } } else if (in_literal) { if (in_escape) in_escape = FALSE; else if (tchar == escape_in_literal) in_escape = TRUE; else if (tchar == literal_quote) in_literal = FALSE; } else if (in_identifier) { if (tchar == identifier_quote) in_identifier = FALSE; } else { if (tchar == '?') { if (0 == num_p && bchar == '{') { if (proc_return) *proc_return = 1; } num_p++; } else if (tchar == ';') { del_found = TRUE; if (next_cmd) *next_cmd = sptr - query; } else if (tchar == dollar_quote) { taglen = findTag(sptr, dollar_quote, encstr.ccsc); if (taglen > 0) { in_dollar_quote = TRUE; tag = sptr; sptr += (taglen - 1); encoded_position_shift(&encstr, taglen - 1); } else num_p++; } else if (tchar == literal_quote) { in_literal = TRUE; escape_in_literal = CC_get_escape(conn); if (!escape_in_literal) { if (LITERAL_EXT == sptr[-1]) escape_in_literal = ESCAPE_IN_LITERAL; } } else if (tchar == identifier_quote) in_identifier = TRUE; if (!isspace(tchar)) bchar = tchar; } } if (pcpar) *pcpar = num_p; if (multi_st) *multi_st = multi;}/* * Pre-execute a statement (for SQLPrepare/SQLDescribeCol) */Int4 /* returns # of fields if successful */SC_pre_execute(StatementClass *self){ Int4 num_fields = -1; QResultClass *res; mylog("SC_pre_execute: status = %d\n", self->status); res = SC_get_Curres(self); if (res && (num_fields = QR_NumResultCols(res)) > 0) return num_fields; if (self->status == STMT_READY) { mylog(" preprocess: status = READY\n"); self->miscinfo = 0; if (self->statement_type == STMT_TYPE_SELECT) { char old_pre_executing = self->pre_executing; decideHowToPrepare(self, FALSE); self->inaccurate_result = FALSE; switch (SC_get_prepare_method(self)) { case NAMED_PARSE_REQUEST: case PARSE_TO_EXEC_ONCE: if (SQL_SUCCESS != prepareParameters(self)) return num_fields; break; case PARSE_REQ_FOR_INFO: if (SQL_SUCCESS != prepareParameters(self)) return num_fields; self->status = STMT_PREMATURE; self->inaccurate_result = TRUE; break; default: self->pre_executing = TRUE; PGAPI_Execute(self, 0); self->pre_executing = old_pre_executing; if (self->status == STMT_FINISHED)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -