static zend_long pgsql_handle_doer(pdo_dbh_t *dbh, const char *sql, zend_long sql_len) { pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; PGresult *res; zend_long ret = 1; ExecStatusType qs; if (!(res = PQexec(H->server, sql))) { /* fatal error */ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, NULL); return -1; } qs = PQresultStatus(res); if (qs != PGRES_COMMAND_OK && qs != PGRES_TUPLES_OK) { pdo_pgsql_error(dbh, qs, pdo_pgsql_sqlstate(res)); PQclear(res); return -1; } H->pgoid = PQoidValue(res); if (qs == PGRES_COMMAND_OK) { ZEND_ATOL(ret, PQcmdTuples(res)); } else { ret = Z_L(0); } PQclear(res); return ret; }
unsigned long psMysqlConnection::Command(const char *sql,...) { psStopWatch timer; csString querystr; va_list args; va_start(args, sql); querystr.FormatV(sql, args); va_end(args); lastquery = querystr; timer.Start(); PGresult *res = PQexec(conn, querystr.GetData()); if(res && PQresultStatus(res) != PGRES_FATAL_ERROR) { if(timer.Stop() > 1000) { csString status; status.Format("SQL query %s, has taken %u time to process.\n", querystr.GetData(), timer.Stop()); if(logcsv) logcsv->Write(CSV_STATUS, status); } profs.AddSQLTime(querystr, timer.Stop()); lastRow = PQoidValue(res); const char *const RowsStr = PQcmdTuples(res); return (unsigned long) (RowsStr[0] ? atoi(RowsStr) : 0); } else { PQclear(res); return QUERY_FAILED; } }
/* * call-seq: * res.oid_value() -> Fixnum * * Returns the +oid+ of the inserted row if applicable, * otherwise +nil+. */ static VALUE pgresult_oid_value(VALUE self) { Oid n = PQoidValue(pgresult_get(self)); if (n == InvalidOid) return Qnil; else return INT2FIX(n); }
QVariant QPSQLResult::lastInsertId() const { if (isActive()) { Oid id = PQoidValue(d->result); if (id != InvalidOid) return QVariant(id); } return QVariant(); }
/* * PrintQueryResults: print out query results as required * * Note: Utility function for use by SendQuery() only. * * Returns true if the query executed successfully, false otherwise. */ static bool PrintQueryResults(PGresult *results) { bool success = false; if (!results) return false; switch (PQresultStatus(results)) { case PGRES_TUPLES_OK: success = PrintQueryTuples(results); break; case PGRES_COMMAND_OK: { char buf[10]; success = true; sprintf(buf, "%u", (unsigned int) PQoidValue(results)); if (!QUIET()) { if (pset.popt.topt.format == PRINT_HTML) { fputs("<p>", pset.queryFout); html_escaped_print(PQcmdStatus(results), pset.queryFout); fputs("</p>\n", pset.queryFout); } else fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); } SetVariable(pset.vars, "LASTOID", buf); break; } case PGRES_EMPTY_QUERY: success = true; break; case PGRES_COPY_OUT: case PGRES_COPY_IN: /* nothing to do here */ success = true; break; default: break; } fflush(pset.queryFout); return success; }
/* function to call for inserts or updates, returns # of rows affected */ int pgconn_update(PGConnection *conn, const char *query) { int rowsModified; PGresult *res; res = PQexec(conn->stream,query); if(res == NULL) THROW("SQLException", "%s", PQerrorMessage(conn->stream)); if(PQresultStatus(res) != PGRES_COMMAND_OK) THROW("SQLException", "%s", PQresultErrorMessage(res)); rowsModified = strtol(PQcmdTuples(res), NULL, 10); lastOid = PQoidValue(res); PQclear(res); return rowsModified; }
static void esql_postgresql_res(Esql_Res *res) { Esql_Row *r; PGresult *pres; int i; pres = res->backend.res = PQgetResult(res->e->backend.db); EINA_SAFETY_ON_NULL_RETURN(pres); switch (PQresultStatus(pres)) { case PGRES_COMMAND_OK: { const char *a; a = PQcmdTuples(pres); if (a && (*a)) res->affected = strtol(a, NULL, 10); res->id = PQoidValue(pres); } return; case PGRES_TUPLES_OK: break; default: res->error = PQresultErrorMessage(pres); ERR("Error %s:'%s'!", PQresStatus(PQresultStatus(pres)), res->error); return; } res->desc = esql_module_desc_get(PQntuples(pres), (Esql_Module_Setup_Cb)esql_module_setup_cb, res); for (i = 0; i < res->row_count; i++) { r = esql_row_calloc(1); EINA_SAFETY_ON_NULL_RETURN(r); r->res = res; esql_postgresql_row_init(r, i); res->rows = eina_inlist_append(res->rows, EINA_INLIST_GET(r)); } }
/* * Find the max of the lastOid values returned from the QEs */ Oid cdbdisp_maxLastOid(CdbDispatchResults *results, int sliceIndex) { CdbDispatchResult *dispatchResult; CdbDispatchResult *resultEnd = cdbdisp_resultEnd(results, sliceIndex); PGresult *pgresult; Oid oid = InvalidOid; for (dispatchResult = cdbdisp_resultBegin(results, sliceIndex); dispatchResult < resultEnd; ++dispatchResult) { pgresult = cdbdisp_getPGresult(dispatchResult, dispatchResult->okindex); if (pgresult && !dispatchResult->errcode) { Oid tmpoid = PQoidValue(pgresult); if (tmpoid > oid) oid = tmpoid; } } return oid; }
/* * PrintQueryStatus: report command status as required * * Note: Utility function for use by PrintQueryResults() only. */ static void PrintQueryStatus(PGresult *results) { char buf[16]; if (!pset.quiet) { if (pset.popt.topt.format == PRINT_HTML) { fputs("<p>", pset.queryFout); html_escaped_print(PQcmdStatus(results), pset.queryFout); fputs("</p>\n", pset.queryFout); } else fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); } if (pset.logfile) fprintf(pset.logfile, "%s\n", PQcmdStatus(results)); snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results)); SetVariable(pset.vars, "LASTOID", buf); }
ngx_chain_t * ngx_postgres_render_rds_header(ngx_http_request_t *r, ngx_pool_t *pool, PGresult *res, ngx_int_t col_count, ngx_int_t aff_count) { ngx_chain_t *cl; ngx_buf_t *b; size_t size; char *errstr; size_t errstr_len; dd("entering"); errstr = PQresultErrorMessage(res); errstr_len = ngx_strlen(errstr); size = sizeof(uint8_t) /* endian type */ + sizeof(uint32_t) /* format version */ + sizeof(uint8_t) /* result type */ + sizeof(uint16_t) /* standard error code */ + sizeof(uint16_t) /* driver-specific error code */ + sizeof(uint16_t) /* driver-specific error string length */ + (uint16_t) errstr_len /* driver-specific error string data */ + sizeof(uint64_t) /* rows affected */ + sizeof(uint64_t) /* insert id */ + sizeof(uint16_t) /* column count */ ; b = ngx_create_temp_buf(pool, size); if (b == NULL) { dd("returning NULL"); return NULL; } cl = ngx_alloc_chain_link(pool); if (cl == NULL) { dd("returning NULL"); return NULL; } cl->buf = b; b->memory = 1; b->tag = r->upstream->output.tag; /* fill data */ #if NGX_HAVE_LITTLE_ENDIAN *b->last++ = 0; #else *b->last++ = 1; #endif *(uint32_t *) b->last = (uint32_t) resty_dbd_stream_version; b->last += sizeof(uint32_t); *b->last++ = 0; *(uint16_t *) b->last = (uint16_t) 0; b->last += sizeof(uint16_t); *(uint16_t *) b->last = (uint16_t) PQresultStatus(res); b->last += sizeof(uint16_t); *(uint16_t *) b->last = (uint16_t) errstr_len; b->last += sizeof(uint16_t); if (errstr_len) { b->last = ngx_copy(b->last, (u_char *) errstr, errstr_len); } *(uint64_t *) b->last = (uint64_t) aff_count; b->last += sizeof(uint64_t); *(uint64_t *) b->last = (uint64_t) PQoidValue(res); b->last += sizeof(uint64_t); *(uint16_t *) b->last = (uint16_t) col_count; b->last += sizeof(uint16_t); if (b->last != b->end) { dd("returning NULL"); return NULL; } dd("returning"); return cl; }
/********************************** * pg_result get information about the results of a query syntax: pg_result result ?option? the options are: -status the status of the result -error the error message, if the status indicates error; otherwise an empty string -conn the connection that produced the result -oid if command was an INSERT, the OID of the inserted tuple -numTuples the number of tuples in the query -cmdTuples the number of tuples affected by the query -numAttrs returns the number of attributes returned by the query -assign arrayName assign the results to an array, using subscripts of the form (tupno,attributeName) -assignbyidx arrayName ?appendstr? assign the results to an array using the first field's value as a key. All but the first field of each tuple are stored, using subscripts of the form (field0value,attributeNameappendstr) -getTuple tupleNumber returns the values of the tuple in a list -tupleArray tupleNumber arrayName stores the values of the tuple in array arrayName, indexed by the attributes returned -attributes returns a list of the name/type pairs of the tuple attributes -lAttributes returns a list of the {name type len} entries of the tuple attributes -clear clear the result buffer. Do not reuse after this **********************************/ int Pg_result(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { PGresult *result; const char *opt; int i; int tupno; CONST84 char *arrVar; char nameBuffer[256]; const char *appendstr; if (argc < 3 || argc > 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", 0); goto Pg_result_errReturn; /* append help info */ } result = PgGetResultId(interp, argv[1]); if (result == (PGresult *) NULL) { Tcl_AppendResult(interp, "\n", argv[1], " is not a valid query result", 0); return TCL_ERROR; } opt = argv[2]; if (strcmp(opt, "-status") == 0) { Tcl_AppendResult(interp, PQresStatus(PQresultStatus(result)), 0); return TCL_OK; } else if (strcmp(opt, "-error") == 0) { Tcl_SetResult(interp, (char *) PQresultErrorMessage(result), TCL_STATIC); return TCL_OK; } else if (strcmp(opt, "-conn") == 0) return PgGetConnByResultId(interp, argv[1]); else if (strcmp(opt, "-oid") == 0) { sprintf(interp->result, "%u", PQoidValue(result)); return TCL_OK; } else if (strcmp(opt, "-clear") == 0) { PgDelResultId(interp, argv[1]); PQclear(result); return TCL_OK; } else if (strcmp(opt, "-numTuples") == 0) { sprintf(interp->result, "%d", PQntuples(result)); return TCL_OK; } else if (strcmp(opt, "-cmdTuples") == 0) { sprintf(interp->result, "%s", PQcmdTuples(result)); return TCL_OK; } else if (strcmp(opt, "-numAttrs") == 0) { sprintf(interp->result, "%d", PQnfields(result)); return TCL_OK; } else if (strcmp(opt, "-assign") == 0) { if (argc != 4) { Tcl_AppendResult(interp, "-assign option must be followed by a variable name", 0); return TCL_ERROR; } arrVar = argv[3]; /* * this assignment assigns the table of result tuples into a giant * array with the name given in the argument. The indices of the * array are of the form (tupno,attrName). Note we expect field * names not to exceed a few dozen characters, so truncating to * prevent buffer overflow shouldn't be a problem. */ for (tupno = 0; tupno < PQntuples(result); tupno++) { for (i = 0; i < PQnfields(result); i++) { sprintf(nameBuffer, "%d,%.200s", tupno, PQfname(result, i)); if (Tcl_SetVar2(interp, arrVar, nameBuffer, #ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)), #else PQgetvalue(result, tupno, i), #endif TCL_LEAVE_ERR_MSG) == NULL) return TCL_ERROR; } } Tcl_AppendResult(interp, arrVar, 0); return TCL_OK; } else if (strcmp(opt, "-assignbyidx") == 0) { if (argc != 4 && argc != 5) { Tcl_AppendResult(interp, "-assignbyidx option requires an array name and optionally an append string", 0); return TCL_ERROR; } arrVar = argv[3]; appendstr = (argc == 5) ? (const char *) argv[4] : ""; /* * this assignment assigns the table of result tuples into a giant * array with the name given in the argument. The indices of the * array are of the form (field0Value,attrNameappendstr). Here, we * still assume PQfname won't exceed 200 characters, but we dare * not make the same assumption about the data in field 0 nor the * append string. */ for (tupno = 0; tupno < PQntuples(result); tupno++) { const char *field0 = #ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, 0)); #else PQgetvalue(result, tupno, 0); #endif char *workspace = malloc(strlen(field0) + strlen(appendstr) + 210); for (i = 1; i < PQnfields(result); i++) { sprintf(workspace, "%s,%.200s%s", field0, PQfname(result, i), appendstr); if (Tcl_SetVar2(interp, arrVar, workspace, #ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)), #else PQgetvalue(result, tupno, i), #endif TCL_LEAVE_ERR_MSG) == NULL) { free(workspace); return TCL_ERROR; } } free(workspace); } Tcl_AppendResult(interp, arrVar, 0); return TCL_OK; } else if (strcmp(opt, "-getTuple") == 0) { if (argc != 4) { Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number", 0); return TCL_ERROR; } tupno = atoi(argv[3]); if (tupno < 0 || tupno >= PQntuples(result)) { Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1", 0); return TCL_ERROR; } #ifdef TCL_ARRAYS for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i))); #else for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, PQgetvalue(result, tupno, i)); #endif return TCL_OK; } else if (strcmp(opt, "-tupleArray") == 0) { if (argc != 5) { Tcl_AppendResult(interp, "-tupleArray option must be followed by a tuple number and array name", 0); return TCL_ERROR; } tupno = atoi(argv[3]); if (tupno < 0 || tupno >= PQntuples(result)) { Tcl_AppendResult(interp, "argument to tupleArray cannot exceed number of tuples - 1", 0); return TCL_ERROR; } for (i = 0; i < PQnfields(result); i++) { if (Tcl_SetVar2(interp, argv[4], PQfname(result, i), #ifdef TCL_ARRAYS tcl_value(PQgetvalue(result, tupno, i)), #else PQgetvalue(result, tupno, i), #endif TCL_LEAVE_ERR_MSG) == NULL) return TCL_ERROR; } return TCL_OK; } else if (strcmp(opt, "-attributes") == 0) { for (i = 0; i < PQnfields(result); i++) Tcl_AppendElement(interp, PQfname(result, i)); return TCL_OK; } else if (strcmp(opt, "-lAttributes") == 0) { for (i = 0; i < PQnfields(result); i++) { /* start a sublist */ if (i > 0) Tcl_AppendResult(interp, " {", 0); else Tcl_AppendResult(interp, "{", 0); Tcl_AppendElement(interp, PQfname(result, i)); sprintf(nameBuffer, "%ld", (long) PQftype(result, i)); Tcl_AppendElement(interp, nameBuffer); sprintf(nameBuffer, "%ld", (long) PQfsize(result, i)); Tcl_AppendElement(interp, nameBuffer); /* end the sublist */ Tcl_AppendResult(interp, "}", 0); } return TCL_OK; } else { Tcl_AppendResult(interp, "Invalid option\n", 0); goto Pg_result_errReturn; /* append help info */ } Pg_result_errReturn: Tcl_AppendResult(interp, "pg_result result ?option? where option is\n", "\t-status\n", "\t-error\n", "\t-conn\n", "\t-oid\n", "\t-numTuples\n", "\t-cmdTuples\n", "\t-numAttrs\n" "\t-assign arrayVarName\n", "\t-assignbyidx arrayVarName ?appendstr?\n", "\t-getTuple tupleNumber\n", "\t-tupleArray tupleNumber arrayVarName\n", "\t-attributes\n" "\t-lAttributes\n" "\t-clear\n", (char *) 0); return TCL_ERROR; }
int pgQueryThread::execute() { rowsInserted = -1L; if (!conn->conn) return(raiseEvent(0)); wxCharBuffer queryBuf = query.mb_str(*conn->conv); if (!queryBuf && !query.IsEmpty()) { conn->SetLastResultError(NULL, _("The query could not be converted to the required encoding.")); return(raiseEvent(0)); } if (!PQsendQuery(conn->conn, queryBuf)) { conn->SetLastResultError(NULL); conn->IsAlive(); return(raiseEvent(0)); } int resultsRetrieved = 0; PGresult *lastResult = 0; while (true) { if (TestDestroy()) { if (rc != -3) { if (!PQrequestCancel(conn->conn)) // could not abort; abort failed. return(raiseEvent(-1)); rc = -3; } } if (!PQconsumeInput(conn->conn)) return(raiseEvent(0)); if (PQisBusy(conn->conn)) { Yield(); this->Sleep(10); continue; } // If resultToRetrieve is given, the nth result will be returned, // otherwise the last result set will be returned. // all others are discarded PGresult *res = PQgetResult(conn->conn); if (!res) break; resultsRetrieved++; if (resultsRetrieved == resultToRetrieve) { result = res; insertedOid = PQoidValue(res); if (insertedOid && insertedOid != (OID) - 1) appendMessage(wxString::Format(_("Query inserted one row with OID %d.\n"), insertedOid)); else appendMessage(wxString::Format(wxPLURAL("Query result with %d row will be returned.\n", "Query result with %d rows will be returned.\n", PQntuples(result)))); continue; } if (lastResult) { if (PQntuples(lastResult)) appendMessage(wxString::Format(wxPLURAL("Query result with %d row discarded.\n", "Query result with %d rows discarded.\n", PQntuples(lastResult)))); PQclear(lastResult); } lastResult = res; } if (!result) result = lastResult; conn->SetLastResultError(result); appendMessage(wxT("\n")); rc = PQresultStatus(result); insertedOid = PQoidValue(result); if (insertedOid == (OID) - 1) insertedOid = 0; if (rc == PGRES_TUPLES_OK) { dataSet = new pgSet(result, conn, *conn->conv, conn->needColQuoting); dataSet->MoveFirst(); } else if (rc == PGRES_COMMAND_OK) { char *s = PQcmdTuples(result); if (*s) rowsInserted = atol(s); } else if (rc == PGRES_FATAL_ERROR) { appendMessage(conn->GetLastError() + wxT("\n")); } return(raiseEvent(1)); }
int Pg_execute(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) { Pg_ConnectionId *connid; PGconn *conn; PGresult *result; int i; int tupno; int ntup; int loop_rc; CONST84 char *oid_varname = NULL; CONST84 char *array_varname = NULL; char buf[64]; char *usage = "Wrong # of arguments\n" "pg_execute ?-array arrayname? ?-oid varname? " "connection queryString ?loop_body?"; /* * First we parse the options */ i = 1; while (i < argc) { if (argv[i][0] != '-') break; if (strcmp(argv[i], "-array") == 0) { /* * The rows should appear in an array vs. to single variables */ i++; if (i == argc) { Tcl_SetResult(interp, usage, TCL_VOLATILE); return TCL_ERROR; } array_varname = argv[i++]; continue; } if (strcmp(argv[i], "-oid") == 0) { /* * We should place PQoidValue() somewhere */ i++; if (i == argc) { Tcl_SetResult(interp, usage, TCL_VOLATILE); return TCL_ERROR; } oid_varname = argv[i++]; continue; } Tcl_AppendResult(interp, "Unknown option '", argv[i], "'", NULL); return TCL_ERROR; } /* * Check that after option parsing at least 'connection' and 'query' * are left */ if (argc - i < 2) { Tcl_SetResult(interp, usage, TCL_VOLATILE); return TCL_ERROR; } /* * Get the connection and make sure no COPY command is pending */ conn = PgGetConnectionId(interp, argv[i++], &connid); if (conn == (PGconn *) NULL) return TCL_ERROR; if (connid->res_copyStatus != RES_COPY_NONE) { Tcl_SetResult(interp, "Attempt to query while COPY in progress", TCL_STATIC); return TCL_ERROR; } /* * Execute the query */ result = PQexec(conn, argv[i++]); /* * Transfer any notify events from libpq to Tcl event queue. */ PgNotifyTransferEvents(connid); /* * Check for errors */ if (result == NULL) { Tcl_SetResult(interp, PQerrorMessage(conn), TCL_VOLATILE); return TCL_ERROR; } /* * Set the oid variable to the returned oid of an INSERT statement if * requested (or 0 if it wasn't an INSERT) */ if (oid_varname != NULL) { char oid_buf[32]; sprintf(oid_buf, "%u", PQoidValue(result)); if (Tcl_SetVar(interp, oid_varname, oid_buf, TCL_LEAVE_ERR_MSG) == NULL) { PQclear(result); return TCL_ERROR; } } /* * Decide how to go on based on the result status */ switch (PQresultStatus(result)) { case PGRES_TUPLES_OK: /* fall through if we have tuples */ break; case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: case PGRES_COPY_IN: case PGRES_COPY_OUT: /* tell the number of affected tuples for non-SELECT queries */ Tcl_SetResult(interp, PQcmdTuples(result), TCL_VOLATILE); PQclear(result); return TCL_OK; default: /* anything else must be an error */ Tcl_ResetResult(interp); Tcl_AppendElement(interp, PQresStatus(PQresultStatus(result))); Tcl_AppendElement(interp, PQresultErrorMessage(result)); PQclear(result); return TCL_ERROR; } /* * We reach here only for queries that returned tuples */ if (i == argc) { /* * We don't have a loop body. If we have at least one result row, * we set all the variables to the first one and return. */ if (PQntuples(result) > 0) { if (execute_put_values(interp, array_varname, result, 0) != TCL_OK) { PQclear(result); return TCL_ERROR; } } sprintf(buf, "%d", PQntuples(result)); Tcl_SetResult(interp, buf, TCL_VOLATILE); PQclear(result); return TCL_OK; } /* * We have a loop body. For each row in the result set put the values * into the Tcl variables and execute the body. */ ntup = PQntuples(result); for (tupno = 0; tupno < ntup; tupno++) { if (execute_put_values(interp, array_varname, result, tupno) != TCL_OK) { PQclear(result); return TCL_ERROR; } loop_rc = Tcl_Eval(interp, argv[i]); /* The returncode of the loop body controls the loop execution */ if (loop_rc == TCL_OK || loop_rc == TCL_CONTINUE) /* OK or CONTINUE means start next loop invocation */ continue; if (loop_rc == TCL_RETURN) { /* RETURN means hand up the given interpreter result */ PQclear(result); return TCL_RETURN; } if (loop_rc == TCL_BREAK) /* BREAK means leave the loop */ break; PQclear(result); return TCL_ERROR; } /* * At the end of the loop we put the number of rows we got into the * interpreter result and clear the result set. */ sprintf(buf, "%d", ntup); Tcl_SetResult(interp, buf, TCL_VOLATILE); PQclear(result); return TCL_OK; }
Oid oid_value() const { Oid o = PQoidValue(res); if (o == InvalidOid) throw Error::no_insert("", conn.getName()); return o; }
int pgQueryThread::Execute() { wxMutexLocker lock(m_queriesLock); PGresult *result = NULL; wxMBConv &conv = *(m_conn->conv); wxString &query = m_queries[m_currIndex]->m_query; int &resultToRetrieve = m_queries[m_currIndex]->m_resToRetrieve; long &rowsInserted = m_queries[m_currIndex]->m_rowsInserted; Oid &insertedOid = m_queries[m_currIndex]->m_insertedOid; // using the alias for the pointer here, in order to save the result back // in the pgBatchQuery object pgSet *&dataSet = m_queries[m_currIndex]->m_resultSet; int &rc = m_queries[m_currIndex]->m_returnCode; pgParamsArray *params = m_queries[m_currIndex]->m_params; bool useCallable = m_queries[m_currIndex]->m_useCallable; pgError &err = m_queries[m_currIndex]->m_err; wxCharBuffer queryBuf = query.mb_str(conv); if (PQstatus(m_conn->conn) != CONNECTION_OK) { rc = pgQueryResultEvent::PGQ_CONN_LOST; err.msg_primary = _("Connection to the database server lost"); return(RaiseEvent(rc)); } if (!queryBuf && !query.IsEmpty()) { rc = pgQueryResultEvent::PGQ_STRING_INVALID; m_conn->SetLastResultError(NULL, _("the query could not be converted to the required encoding.")); err.msg_primary = _("Query string is empty"); return(RaiseEvent(rc)); } // Honour the parameters (if any) if (params && params->GetCount() > 0) { int pCount = params->GetCount(); int ret = 0, idx = 0; Oid *pOids = (Oid *)malloc(pCount * sizeof(Oid)); const char **pParams = (const char **)malloc(pCount * sizeof(const char *)); int *pLens = (int *)malloc(pCount * sizeof(int)); int *pFormats = (int *)malloc(pCount * sizeof(int)); // modes are used only by enterprisedb callable statement #if defined (__WXMSW__) || (EDB_LIBPQ) int *pModes = (int *)malloc(pCount * sizeof(int)); #endif for (; idx < pCount; idx++) { pgParam *param = (*params)[idx]; pOids[idx] = param->m_type; pParams[idx] = (const char *)param->m_val; pLens[idx] = param->m_len; pFormats[idx] = param->GetFormat(); #if defined (__WXMSW__) || (EDB_LIBPQ) pModes[idx] = param->m_mode; #endif } if (useCallable) { #if defined (__WXMSW__) || (EDB_LIBPQ) wxLogInfo(wxString::Format( _("using an enterprisedb callable statement (queryid:%ld, threadid:%ld)"), (long)m_currIndex, (long)GetId())); wxString stmt = wxString::Format(wxT("pgQueryThread-%ld-%ld"), this->GetId(), m_currIndex); PGresult *res = PQiPrepareOut(m_conn->conn, stmt.mb_str(wxConvUTF8), queryBuf, pCount, pOids, pModes); if( PQresultStatus(res) != PGRES_COMMAND_OK) { rc = pgQueryResultEvent::PGQ_ERROR_PREPARE_CALLABLE; err.SetError(res, &conv); PQclear(res); goto return_with_error; } ret = PQiSendQueryPreparedOut(m_conn->conn, stmt.mb_str(wxConvUTF8), pCount, pParams, pLens, pFormats, 1); if (ret != 1) { rc = pgQueryResultEvent::PGQ_ERROR_EXECUTE_CALLABLE; m_conn->SetLastResultError(NULL, _("Failed to run PQsendQuery in pgQueryThread")); err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); PQclear(res); res = NULL; goto return_with_error; } PQclear(res); res = NULL; #else rc = -1; wxASSERT_MSG(false, _("the program execution flow must not reach to this point in pgQueryThread")); goto return_with_error; #endif } else { // assumptions: we will need the results in text format only ret = PQsendQueryParams(m_conn->conn, queryBuf, pCount, pOids, pParams, pLens, pFormats, 0); if (ret != 1) { rc = pgQueryResultEvent::PGQ_ERROR_SEND_QUERY; m_conn->SetLastResultError(NULL, _("Failed to run PQsendQueryParams in pgQueryThread")); err.msg_primary = _("Failed to run PQsendQueryParams in pgQueryThread.\n") + wxString(PQerrorMessage(m_conn->conn), conv); goto return_with_error; } } goto continue_without_error; return_with_error: { free(pOids); free(pParams); free(pLens); free(pFormats); #if defined (__WXMSW__) || (EDB_LIBPQ) free(pModes); #endif return (RaiseEvent(rc)); } } else { // use the PQsendQuery api in case, we don't have any parameters to // pass to the server if (!PQsendQuery(m_conn->conn, queryBuf)) { rc = pgQueryResultEvent::PGQ_ERROR_SEND_QUERY; err.msg_primary = _("Failed to run PQsendQueryParams in pgQueryThread.\n") + wxString(PQerrorMessage(m_conn->conn), conv); return(RaiseEvent(rc)); } } continue_without_error: int resultsRetrieved = 0; PGresult *lastResult = 0; while (true) { // This is a 'joinable' thread, it is not advisable to call 'delete' // function on this. // Hence - it does not make sense to use the function 'testdestroy' here. // We introduced the 'CancelExecution' function for the same purpose. // // Also, do not raise event when the query execution is cancelled to // avoid the bugs introduced to handle events by the event handler, // which is missing or being deleted. // // It will be responsibility of the compononent, using the object of // pgQueryThread, to take the required actions to take care of the // issue. if (m_cancelled) { m_conn->CancelExecution(); rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; err.msg_primary = _("Execution Cancelled"); if (lastResult) { PQclear(lastResult); lastResult = NULL; } AppendMessage(_("Query-thread execution cancelled...\nthe query is:")); AppendMessage(query); return rc; } if ((rc = PQconsumeInput(m_conn->conn)) != 1) { if (rc == 0) { err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); } if (PQstatus(m_conn->conn) == CONNECTION_BAD) { err.msg_primary = _("Connection to the database server lost"); rc = pgQueryResultEvent::PGQ_CONN_LOST; } else { rc = pgQueryResultEvent::PGQ_ERROR_CONSUME_INPUT; } return(RaiseEvent(rc)); } if (PQisBusy(m_conn->conn)) { Yield(); this->Sleep(10); continue; } // if resultToRetrieve is given, the nth result will be returned, // otherwise the last result set will be returned. // all others are discarded PGresult *res = PQgetResult(m_conn->conn); if (!res) break; if((PQresultStatus(res) == PGRES_NONFATAL_ERROR) || (PQresultStatus(res) == PGRES_FATAL_ERROR) || (PQresultStatus(res) == PGRES_BAD_RESPONSE)) { result = res; err.SetError(res, &conv); // Wait for the execution to be finished // We need to fetch all the results, before sending the error // message do { if (PQconsumeInput(m_conn->conn) != 1) { if (m_cancelled) { rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; // Release the result as the query execution has been cancelled by the // user if (result) PQclear(result); return rc; } goto out_of_consume_input_loop; } if ((res = PQgetResult(m_conn->conn)) == NULL) { goto out_of_consume_input_loop; } // Release the temporary results PQclear(res); res = NULL; if (PQisBusy(m_conn->conn)) { Yield(); this->Sleep(10); } } while (true); break; } #if defined (__WXMSW__) || (EDB_LIBPQ) // there should be 2 results in the callable statement - the first is the // dummy, the second contains our out params. if (useCallable) { PQclear(res); result = PQiGetOutResult(m_conn->conn); } #endif if (PQresultStatus(res) == PGRES_COPY_IN) { rc = PGRES_COPY_IN; PQputCopyEnd(m_conn->conn, "not supported by pgadmin"); } if (PQresultStatus(res) == PGRES_COPY_OUT) { int copyRc; char *buf; int copyRows = 0; int lastCopyRc = 0; rc = PGRES_COPY_OUT; AppendMessage(_("query returned copy data:\n")); while((copyRc = PQgetCopyData(m_conn->conn, &buf, 1)) >= 0) { if (buf != NULL) { if (copyRows < 100) { wxString str(buf, conv); wxCriticalSectionLocker cs(m_criticalSection); m_queries[m_currIndex]->m_message.Append(str); } else if (copyRows == 100) AppendMessage(_("Query returned more than 100 copy rows, discarding the rest...\n")); PQfreemem(buf); } if (copyRc > 0) copyRows++; if (m_cancelled) { m_conn->CancelExecution(); rc = pgQueryResultEvent::PGQ_EXECUTION_CANCELLED; return -1; } if (lastCopyRc == 0 && copyRc == 0) { Yield(); this->Sleep(10); } if (copyRc == 0) { if (!PQconsumeInput(m_conn->conn)) { if (PQstatus(m_conn->conn) == CONNECTION_BAD) { err.msg_primary = _("Connection to the database server lost"); rc = pgQueryResultEvent::PGQ_CONN_LOST; } else { rc = pgQueryResultEvent::PGQ_ERROR_CONSUME_INPUT; err.msg_primary = wxString(PQerrorMessage(m_conn->conn), conv); } return(RaiseEvent(rc)); } } lastCopyRc = copyRc; } res = PQgetResult(m_conn->conn); if (!res) break; } resultsRetrieved++; if (resultsRetrieved == resultToRetrieve) { result = res; insertedOid = PQoidValue(res); if (insertedOid && insertedOid != (Oid) - 1) AppendMessage(wxString::Format(_("query inserted one row with oid %d.\n"), insertedOid)); else AppendMessage(wxString::Format(wxPLURAL("query result with %d row will be returned.\n", "query result with %d rows will be returned.\n", PQntuples(result)), PQntuples(result))); continue; } if (lastResult) { if (PQntuples(lastResult)) AppendMessage(wxString::Format(wxPLURAL("query result with %d row discarded.\n", "query result with %d rows discarded.\n", PQntuples(lastResult)), PQntuples(lastResult))); PQclear(lastResult); } lastResult = res; } out_of_consume_input_loop: if (!result) result = lastResult; err.SetError(result, &conv); AppendMessage(wxT("\n")); rc = PQresultStatus(result); if (rc == PGRES_TUPLES_OK) { dataSet = new pgSet(result, m_conn, conv, m_conn->needColQuoting); dataSet->MoveFirst(); } else if (rc == PGRES_COMMAND_OK) { char *s = PQcmdTuples(result); if (*s) rowsInserted = atol(s); } else if (rc == PGRES_FATAL_ERROR || rc == PGRES_NONFATAL_ERROR || rc == PGRES_BAD_RESPONSE) { if (result) { AppendMessage(wxString(PQresultErrorMessage(result), conv)); PQclear(result); result = NULL; } else { AppendMessage(wxString(PQerrorMessage(m_conn->conn), conv)); } return(RaiseEvent(rc)); } insertedOid = PQoidValue(result); if (insertedOid == (Oid) - 1) insertedOid = 0; return(RaiseEvent(1)); }
static int store_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; Oid insertid; char sql[256]; char params[256]; char vals[256]; char buf[256]; int pgresult; const char *newparam, *newval; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return -1; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime storage requires at least 1 parameter and 1 value to store.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return -1; } /* Must connect to the server before anything else, as the escape function requires the connection handle.. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return -1; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ PQescapeStringConn(pgsqlConn, buf, newparam, sizeof(newparam), &pgresult); snprintf(params, sizeof(params), "%s", buf); PQescapeStringConn(pgsqlConn, buf, newval, sizeof(newval), &pgresult); snprintf(vals, sizeof(vals), "'%s'", buf); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); PQescapeStringConn(pgsqlConn, buf, newparam, sizeof(newparam), &pgresult); snprintf(params + strlen(params), sizeof(params) - strlen(params), ", %s", buf); PQescapeStringConn(pgsqlConn, buf, newval, sizeof(newval), &pgresult); snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", '%s'", buf); } va_end(ap); snprintf(sql, sizeof(sql), "INSERT INTO (%s) VALUES (%s)", params, vals); ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", sql); if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return -1; } } insertid = PQoidValue(result); ast_mutex_unlock(&pgsql_lock); ast_debug(1, "PostgreSQL RealTime: row inserted on table: %s, id: %u\n", table, insertid); /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html * An integer greater than zero indicates the number of rows affected * Zero indicates that no records were updated * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) */ if (insertid >= 0) return (int) insertid; return -1; }
long long PostgresqlConnection_lastRowId(T C) { assert(C); return (long long)PQoidValue(C->res); }
static int pgsql_stmt_execute(pdo_stmt_t *stmt) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; pdo_pgsql_db_handle *H = S->H; ExecStatusType status; /* ensure that we free any previous unfetched results */ if(S->result) { PQclear(S->result); S->result = NULL; } S->current_row = 0; if (S->cursor_name) { char *q = NULL; if (S->is_prepared) { spprintf(&q, 0, "CLOSE %s", S->cursor_name); S->result = PQexec(H->server, q); efree(q); } spprintf(&q, 0, "DECLARE %s SCROLL CURSOR WITH HOLD FOR %s", S->cursor_name, stmt->active_query_string); S->result = PQexec(H->server, q); efree(q); /* check if declare failed */ status = PQresultStatus(S->result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result)); return 0; } /* the cursor was declared correctly */ S->is_prepared = 1; /* fetch to be able to get the number of tuples later, but don't advance the cursor pointer */ spprintf(&q, 0, "FETCH FORWARD 0 FROM %s", S->cursor_name); S->result = PQexec(H->server, q); efree(q); } else if (S->stmt_name) { /* using a prepared statement */ if (!S->is_prepared) { stmt_retry: /* we deferred the prepare until now, because we didn't * know anything about the parameter types; now we do */ S->result = PQprepare(H->server, S->stmt_name, S->query, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, S->param_types); status = PQresultStatus(S->result); switch (status) { case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: /* it worked */ S->is_prepared = 1; PQclear(S->result); break; default: { char *sqlstate = pdo_pgsql_sqlstate(S->result); /* 42P05 means that the prepared statement already existed. this can happen if you use * a connection pooling software line pgpool which doesn't close the db-connection once * php disconnects. if php dies (no chance to run RSHUTDOWN) during execution it has no * chance to DEALLOCATE the prepared statements it has created. so, if we hit a 42P05 we * deallocate it and retry ONCE (thies 2005.12.15) */ if (sqlstate && !strcmp(sqlstate, "42P05")) { char buf[100]; /* stmt_name == "pdo_crsr_%08x" */ PGresult *res; snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name); res = PQexec(H->server, buf); if (res) { PQclear(res); } goto stmt_retry; } else { pdo_pgsql_error_stmt(stmt, status, sqlstate); return 0; } } } } S->result = PQexecPrepared(H->server, S->stmt_name, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, (const char**)S->param_values, S->param_lengths, S->param_formats, 0); } else if (stmt->supports_placeholders == PDO_PLACEHOLDER_NAMED) { /* execute query with parameters */ S->result = PQexecParams(H->server, S->query, stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0, S->param_types, (const char**)S->param_values, S->param_lengths, S->param_formats, 0); } else { /* execute plain query (with embedded parameters) */ S->result = PQexec(H->server, stmt->active_query_string); } status = PQresultStatus(S->result); if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK) { pdo_pgsql_error_stmt(stmt, status, pdo_pgsql_sqlstate(S->result)); return 0; } if (!stmt->executed && (!stmt->column_count || S->cols == NULL)) { stmt->column_count = (int) PQnfields(S->result); S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column)); } if (status == PGRES_COMMAND_OK) { ZEND_ATOL(stmt->row_count, PQcmdTuples(S->result)); H->pgoid = PQoidValue(S->result); } else { stmt->row_count = (zend_long)PQntuples(S->result); } return 1; }