/* * Execute SQL statement. For non-select statements only. */ int zbx_db_vexecute(const char *fmt, va_list args) { char *sql = NULL; int ret = ZBX_DB_OK; double sec = 0; #if defined(HAVE_IBM_DB2) SQLHANDLE hstmt = 0; SQLRETURN ret1; SQLLEN row1; SQLLEN rows = 0; #elif defined(HAVE_MYSQL) int status; #elif defined(HAVE_ORACLE) OCIStmt *stmthp = NULL; sword err = OCI_SUCCESS; #elif defined(HAVE_POSTGRESQL) PGresult *result; char *error = NULL; #elif defined(HAVE_SQLITE3) int err; char *error = NULL; #endif if (CONFIG_LOG_SLOW_QUERIES) sec = zbx_time(); sql = fmt; //zabbix_log(LOG_LEVEL_DEBUG,"vexecute: %s",sql); if (0 == txn_init && 0 == txn_level) zabbix_log(LOG_LEVEL_DEBUG, "query without transaction detected"); zabbix_log(LOG_LEVEL_DEBUG, "query [txnlev:%d] [%s]", txn_level, sql); #if defined(HAVE_IBM_DB2) /* allocate a statement handle */ if (SUCCEED != zbx_ibm_db2_success(SQLAllocHandle(SQL_HANDLE_STMT, ibm_db2.hdbc, &hstmt))) ret = ZBX_DB_DOWN; /* directly execute the statement; returns SQL_NO_DATA_FOUND when no rows were affected */ if (ZBX_DB_OK == ret && SUCCEED != zbx_ibm_db2_success_ext(SQLExecDirect(hstmt, (SQLCHAR *)sql, SQL_NTS))) ret = ZBX_DB_DOWN; /* get number of affected rows */ if (ZBX_DB_OK == ret && SUCCEED != zbx_ibm_db2_success(SQLRowCount(hstmt, &rows))) ret = ZBX_DB_DOWN; /* process other SQL statements in the batch */ while (ZBX_DB_OK == ret && SUCCEED == zbx_ibm_db2_success(ret1 = SQLMoreResults(hstmt))) { if (SUCCEED != zbx_ibm_db2_success(SQLRowCount(hstmt, &row1))) ret = ZBX_DB_DOWN; else rows += row1; } if (ZBX_DB_OK == ret && SQL_NO_DATA_FOUND != ret1) ret = ZBX_DB_DOWN; if (ZBX_DB_OK != ret) { zbx_ibm_db2_log_errors(SQL_HANDLE_DBC, ibm_db2.hdbc); zbx_ibm_db2_log_errors(SQL_HANDLE_STMT, hstmt); ret = (SQL_CD_TRUE == IBM_DB2server_status() ? ZBX_DB_FAIL : ZBX_DB_DOWN); } else if (0 <= rows) { ret = (int)rows; } if (hstmt) SQLFreeHandle(SQL_HANDLE_STMT, hstmt); #elif defined(HAVE_MYSQL) if (NULL == conn) { zabbix_errlog(ERR_Z3003); ret = ZBX_DB_FAIL; } else { if (0 != (status = mysql_query(conn, sql))) { zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql); switch (mysql_errno(conn)) { case CR_CONN_HOST_ERROR: case CR_SERVER_GONE_ERROR: case CR_CONNECTION_ERROR: case CR_SERVER_LOST: case ER_SERVER_SHUTDOWN: case ER_ACCESS_DENIED_ERROR: /* wrong user or password */ case ER_ILLEGAL_GRANT_FOR_TABLE: /* user without any privileges */ case ER_TABLEACCESS_DENIED_ERROR:/* user without some privilege */ case ER_UNKNOWN_ERROR: ret = ZBX_DB_DOWN; break; default: ret = ZBX_DB_FAIL; break; } } else { do { if (0 != mysql_field_count(conn)) { zabbix_log(LOG_LEVEL_DEBUG, "cannot retrieve result set"); break; } else ret += (int)mysql_affected_rows(conn); /* more results? -1 = no, >0 = error, 0 = yes (keep looping) */ if (0 < (status = mysql_next_result(conn))) zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql); } while (0 == status); } } #elif defined(HAVE_ORACLE) err = OCIHandleAlloc((dvoid *)oracle.envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0); if (OCI_SUCCESS == err) { err = OCIStmtPrepare(stmthp, oracle.errhp, (text *)sql, (ub4)strlen((char *)sql), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT); } if (OCI_SUCCESS == err) { err = OCIStmtExecute(oracle.svchp, stmthp, oracle.errhp, (ub4)1, (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_COMMIT_ON_SUCCESS); if (OCI_SUCCESS == err) { ub4 nrows = 0; err = OCIAttrGet((void *)stmthp, OCI_HTYPE_STMT, (ub4 *)&nrows, (ub4 *)0, OCI_ATTR_ROW_COUNT, oracle.errhp); ret = nrows; } } if (OCI_SUCCESS != err) { zabbix_errlog(ERR_Z3005, err, zbx_oci_error(err), sql); ret = (OCI_SERVER_NORMAL == OCI_DBserver_status() ? ZBX_DB_FAIL : ZBX_DB_DOWN); } if (NULL != stmthp) { (void)OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT); stmthp = NULL; } #elif defined(HAVE_POSTGRESQL) result = PQexec(conn,sql); if (NULL == result) { zabbix_errlog(ERR_Z3005, 0, "result is NULL", sql); ret = (CONNECTION_OK == PQstatus(conn) ? ZBX_DB_FAIL : ZBX_DB_DOWN); } else if (PGRES_COMMAND_OK != PQresultStatus(result)) { error = zbx_dsprintf(error, "%s:%s", PQresStatus(PQresultStatus(result)), PQresultErrorMessage(result)); zabbix_errlog(ERR_Z3005, 0, error, sql); zbx_free(error); ret = (CONNECTION_OK == PQstatus(conn) ? ZBX_DB_FAIL : ZBX_DB_DOWN); } if (ZBX_DB_OK == ret) ret = atoi(PQcmdTuples(result)); PQclear(result); #elif defined(HAVE_SQLITE3) if (0 == txn_level && PHP_MUTEX_OK != php_sem_acquire(&sqlite_access)) { zabbix_log(LOG_LEVEL_CRIT, "ERROR: unable to create lock on SQLite database"); exit(FAIL); } lbl_exec: if (SQLITE_OK != (err = sqlite3_exec(conn, sql, NULL, 0, &error))) { if (SQLITE_BUSY == err) goto lbl_exec; zabbix_errlog(ERR_Z3005, 0, error, sql); sqlite3_free(error); switch (err) { case SQLITE_ERROR: /* SQL error or missing database; assuming SQL error, because if we are this far into execution, zbx_db_connect() was successful */ case SQLITE_NOMEM: /* A malloc() failed */ case SQLITE_TOOBIG: /* String or BLOB exceeds size limit */ case SQLITE_CONSTRAINT: /* Abort due to constraint violation */ case SQLITE_MISMATCH: /* Data type mismatch */ ret = ZBX_DB_FAIL; break; default: ret = ZBX_DB_DOWN; break; } } if (ZBX_DB_OK == ret) ret = sqlite3_changes(conn); if (0 == txn_level) php_sem_release(&sqlite_access); #endif /* HAVE_SQLITE3 */ if (CONFIG_LOG_SLOW_QUERIES) { sec = zbx_time() - sec; if (sec > (double)CONFIG_LOG_SLOW_QUERIES / 1000.0) zabbix_log(LOG_LEVEL_WARNING, "slow query: " ZBX_FS_DBL " sec, \"%s\"", sec, sql); } return ret; }
int hb_main(const char* conninfo) { PGconn *conn; PGresult *res; PGnotify *notify; int nnotifies; int checked; int result; char number[5]; char notify_buf[1024]; srand((unsigned)time(NULL)); /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { elog(WARNING, "Connection to database failed: %s", PQerrorMessage(conn)); exit_nicely(conn); } /* * Issue LISTEN command to enable notifications from the rule's NOTIFY. */ res = PQexec(conn, "LISTEN HB_SV"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { elog(WARNING, "LISTEN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } /* * should PQclear PGresult whenever it is no longer needed to avoid memory * leaks */ PQclear(res); /* Set Secret Number */ memset(number, 0x00, 5); create_random_number(number); elog(LOG , "hb_worker: set secret number=%s\n", number); /* Quit after four notifies are received. */ nnotifies = 0; while (1) { /* * Sleep until something happens on the connection. We use select(2) * to wait for input, but you could also use poll() or similar * facilities. */ int sock; fd_set input_mask; sock = PQsocket(conn); if (sock < 0) break; /* shouldn't happen */ FD_ZERO(&input_mask); FD_SET(sock, &input_mask); if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0) { elog(WARNING, "select() failed: %s\n", strerror(errno)); exit_nicely(conn); } /* Now check for input */ PQconsumeInput(conn); while ((notify = PQnotifies(conn)) != NULL) { checked = check_number(notify->extra); switch (checked) { case NUMBER_COMMAND: result = compare_numbers(number, notify->extra); if (GET_HITS(result) == 4) { // Notify Game Clear, and Set new number. elog(LOG, "hb_worker: NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'\n"); strcpy(notify_buf, "NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'"); PQexec(conn, notify_buf); create_random_number(number); elog(LOG, "hb_worker: set secret number=%s\n", number); } else { // Notify Hit&blow elog(LOG, "NOTIFY HB_CL,'%d Hit / %d Blow.'", GET_HITS(result), GET_BLOWS(result)); sprintf(notify_buf, "NOTIFY HB_CL,'%d Hit / %d Blow.'", GET_HITS(result), GET_BLOWS(result)); PQexec(conn, notify_buf); } break; case START_COMMAND: // Set New number. elog(LOG, "hb_worker: Set New number."); create_random_number(number); break; case QUIT_COMMAND: // nop break; case INVALID_COMMAND: default: // NOTIFY error status sprintf(notify_buf, "NOTIFY HB_CL,'Invalid data.(%s)'", notify->extra); PQexec(conn, notify_buf); break; } PQfreemem(notify); nnotifies++; } } elog(LOG, "Done.\n"); /* close the connection to the database and cleanup */ PQfinish(conn); return 0; }
/* Complex checking of the query status */ int pgsql_query_checkstatus(PGresult *res) { int status; int nFields; long long nTuples; /* For successful queries, there are two options: either the query returns results or not. If it does not return data, but successfully completed, then the status will be set to PGRES_COMMAND_OK. If success and returns tuples, then it will be set to PGRES_TUPLES_OK */ status = PQresultStatus(res); if (PQresultStatus(res) == PGRES_COMMAND_OK) { /* Success but no results */ IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res)); return(MYPG_NO_RESULT); } if (PQresultStatus(res) != PGRES_TUPLES_OK) { IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQresultErrorMessage(res)); switch (status) { /* No results */ case PGRES_COPY_IN: return(MYPG_NO_RESULT); case PGRES_COPY_OUT: return(MYPG_NO_RESULT); case PGRES_BAD_RESPONSE: return(MYPG_NO_RESULT); case PGRES_NONFATAL_ERROR: return(MYPG_NO_RESULT); /* An error */ case PGRES_FATAL_ERROR: return(MYPG_FATAL_ERROR); default: break; } } /* How many fields and rows did we return? */ nFields = PQnfields(res); nTuples = PQntuples(res); /* Result is empty, either an error or this query returns no data */ if (nTuples == 0) { if (nFields == 0) { /* Query returns no data. Try to print a message to clarify */ IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res)); return(MYPG_NO_RESULT); } else /* Probably nothing matched the query */ return(MYPG_NO_RESULT); } return(MYPG_SUCCESS); }
/* * Establish the connection to the primary server for XLOG streaming */ static bool libpqrcv_connect(char *conninfo, XLogRecPtr startpoint) { char conninfo_repl[MAXCONNINFO + 18]; char *primary_sysid; char standby_sysid[32]; TimeLineID primary_tli; TimeLineID standby_tli; PGresult *res; char cmd[64]; /* Connect using deliberately undocumented parameter: replication */ snprintf(conninfo_repl, sizeof(conninfo_repl), "%s replication=true", conninfo); streamConn = PQconnectdb(conninfo_repl); if (PQstatus(streamConn) != CONNECTION_OK) ereport(ERROR, (errmsg("could not connect to the primary server: %s", PQerrorMessage(streamConn)))); /* * Get the system identifier and timeline ID as a DataRow message from the * primary server. */ res = libpqrcv_PQexec("IDENTIFY_SYSTEM"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { PQclear(res); ereport(ERROR, (errmsg("could not receive database system identifier and timeline ID from " "the primary server: %s", PQerrorMessage(streamConn)))); } if (PQnfields(res) != 2 || PQntuples(res) != 1) { int ntuples = PQntuples(res); int nfields = PQnfields(res); PQclear(res); ereport(ERROR, (errmsg("invalid response from primary server"), errdetail("Expected 1 tuple with 2 fields, got %d tuples with %d fields.", ntuples, nfields))); } primary_sysid = PQgetvalue(res, 0, 0); primary_tli = pg_atoi(PQgetvalue(res, 0, 1), 4, 0); /* * Confirm that the system identifier of the primary is the same as ours. */ snprintf(standby_sysid, sizeof(standby_sysid), UINT64_FORMAT, GetSystemIdentifier()); if (strcmp(primary_sysid, standby_sysid) != 0) { PQclear(res); ereport(ERROR, (errmsg("database system identifier differs between the primary and standby"), errdetail("The primary's identifier is %s, the standby's identifier is %s.", primary_sysid, standby_sysid))); } /* * Confirm that the current timeline of the primary is the same as the * recovery target timeline. */ standby_tli = GetRecoveryTargetTLI(); PQclear(res); if (primary_tli != standby_tli) ereport(ERROR, (errmsg("timeline %u of the primary does not match recovery target timeline %u", primary_tli, standby_tli))); ThisTimeLineID = primary_tli; /* Start streaming from the point requested by startup process */ snprintf(cmd, sizeof(cmd), "START_REPLICATION %X/%X", startpoint.xlogid, startpoint.xrecoff); res = libpqrcv_PQexec(cmd); if (PQresultStatus(res) != PGRES_COPY_OUT) { PQclear(res); ereport(ERROR, (errmsg("could not start WAL streaming: %s", PQerrorMessage(streamConn)))); } PQclear(res); justconnected = true; ereport(LOG, (errmsg("streaming replication successfully connected to primary"))); return true; }
/* * Run one permutation */ static void run_permutation(TestSpec *testspec, int nsteps, Step **steps) { PGresult *res; int i; printf("\nstarting permutation:"); for (i = 0; i < nsteps; i++) printf(" %s", steps[i]->name); printf("\n"); /* Perform setup */ if (testspec->setupsql) { res = PQexec(conns[0], testspec->setupsql); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "setup failed: %s", PQerrorMessage(conns[0])); exit_nicely(); } PQclear(res); } /* Perform per-session setup */ for (i = 0; i < testspec->nsessions; i++) { if (testspec->sessions[i]->setupsql) { res = PQexec(conns[i], testspec->sessions[i]->setupsql); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "setup of session %s failed: %s", testspec->sessions[i]->name, PQerrorMessage(conns[0])); exit_nicely(); } PQclear(res); } } /* Perform steps */ for (i = 0; i < nsteps; i++) { Step *step = steps[i]; printf("step %s: %s\n", step->name, step->sql); res = PQexec(conns[step->session], step->sql); switch(PQresultStatus(res)) { case PGRES_COMMAND_OK: break; case PGRES_TUPLES_OK: printResultSet(res); break; case PGRES_FATAL_ERROR: /* Detail may contain xid values, so just show primary. */ printf("%s: %s\n", PQresultErrorField(res, PG_DIAG_SEVERITY), PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY)); break; default: printf("unexpected result status: %s\n", PQresStatus(PQresultStatus(res))); } PQclear(res); } /* Perform per-session teardown */ for (i = 0; i < testspec->nsessions; i++) { if (testspec->sessions[i]->teardownsql) { res = PQexec(conns[i], testspec->sessions[i]->teardownsql); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "teardown of session %s failed: %s", testspec->sessions[i]->name, PQerrorMessage(conns[0])); /* don't exit on teardown failure */ } PQclear(res); } } /* Perform teardown */ if (testspec->teardownsql) { res = PQexec(conns[0], testspec->teardownsql); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "teardown failed: %s", PQerrorMessage(conns[0])); /* don't exit on teardown failure */ } PQclear(res); } }
/* * Transform a GML geometry to PostGIS EWKT * Return NULL on error */ buffer * ows_psql_gml_to_sql(ows * o, xmlNodePtr n, int srid) { PGresult *res; xmlNodePtr g; buffer *result, *sql, *gml; assert(o); assert(n); g = ows_psql_recursive_parse_gml(o, n, NULL); if (!g) return NULL; /* No Geometry founded in GML doc */ /* Retrieve the sub doc and launch GML parse via PostGIS */ gml = buffer_init(); cgi_add_xml_into_buffer(gml, g); sql = buffer_init(); buffer_add_str(sql, "SELECT ST_GeomFromGML('"); buffer_add_str(sql, gml->buf); if (ows_version_get(o->postgis_version) >= 200) { buffer_add_str(sql, "',"); buffer_add_int(sql, srid); buffer_add_str(sql, ")"); } else { /* Means PostGIS 1.5 */ buffer_add_str(sql, "')"); } res = ows_psql_exec(o, sql->buf); buffer_free(gml); /* GML Parse errors cases */ if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) { buffer_free(sql); PQclear(res); return NULL; } result = buffer_init(); buffer_add_str(result, PQgetvalue(res, 0, 0)); PQclear(res); /* Check if geometry is valid */ if (o->check_valid_geom) { buffer_empty(sql); buffer_add_str(sql, "SELECT ST_IsValid('"); buffer_add_str(sql, result->buf); buffer_add_str(sql, "')"); res = ows_psql_exec(o, sql->buf); if ( PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1 || (char) PQgetvalue(res, 0, 0)[0] != 't') { buffer_free(sql); buffer_free(result); PQclear(res); return NULL; } PQclear(res); } buffer_free(sql); return result; }
/***************************************************** * \brief Read a natural block of raster band data *****************************************************/ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, CPL_UNUSED int nBlockYOff, void * pImage) { CPLString osCommand; PGresult * poResult = NULL; int nWKBLength = 0; int nPixelSize = GDALGetDataTypeSize(eDataType)/8; PostGISRasterTileDataset * poRTDS = (PostGISRasterTileDataset *)poDS; // Get by PKID if (poRTDS->poRDS->pszPrimaryKeyName) { //osCommand.Printf("select ST_AsBinary(st_band(%s, %d),TRUE) from %s.%s where " osCommand.Printf("select st_band(%s, %d) from %s.%s where " "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID); } // Get by upperleft else { osCommand.Printf("select st_band(%s, %d) from %s.%s where " "abs(ST_UpperLeftX(%s) - %.8f) < 1e-8 and abs(ST_UpperLeftY(%s) - %.8f) < 1e-8", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable, poRTDS->poRDS->pszColumn, poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->poRDS->pszColumn, poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]); } poResult = PQexec(poRTDS->poRDS->poConn, osCommand.c_str()); #ifdef DEBUG_QUERY CPLDebug("PostGIS_Raster", "PostGISRasterTileRasterBand::IReadBlock(): " "Query = \"%s\" --> number of rows = %d", osCommand.c_str(), poResult ? PQntuples(poResult) : 0 ); #endif if (poResult == NULL || PQresultStatus(poResult) != PGRES_TUPLES_OK || PQntuples(poResult) <= 0) { if (poResult) PQclear(poResult); ReportError(CE_Failure, CPLE_AppDefined, "Error getting block of data (upperpixel = %f, %f)", poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_X], poRTDS->adfGeoTransform[GEOTRSFRM_TOPLEFT_Y]); return CE_Failure; } // TODO: Check this if (bIsOffline) { CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb " "storage. This feature isn't still available"); PQclear(poResult); return CE_Failure; } /* Copy only data size, without payload */ int nExpectedDataSize = nBlockXSize * nBlockYSize * nPixelSize; GByte * pbyData = CPLHexToBinary(PQgetvalue(poResult, 0, 0), &nWKBLength); int nExpectedWKBLength = RASTER_HEADER_SIZE + BAND_SIZE(nPixelSize, nExpectedDataSize); CPLErr eRet = CE_None; if( nWKBLength != nExpectedWKBLength ) { CPLDebug("PostGIS_Raster", "nWKBLength=%d, nExpectedWKBLength=%d", nWKBLength, nExpectedWKBLength ); eRet = CE_Failure; } else { GByte * pbyDataToRead = (GByte*)GET_BAND_DATA(pbyData,1, nPixelSize, nExpectedDataSize); // Do byte-swapping if necessary */ int bIsLittleEndian = (pbyData[0] == 1); #ifdef CPL_LSB int bSwap = !bIsLittleEndian; #else int bSwap = bIsLittleEndian; #endif if( bSwap && nPixelSize > 1 ) { GDALSwapWords( pbyDataToRead, nPixelSize, nBlockXSize * nBlockYSize, nPixelSize ); } memcpy(pImage, pbyDataToRead, nExpectedDataSize); } CPLFree(pbyData); PQclear(poResult); return eRet; }
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)), 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; } 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)); }
KCSQLResult* PgSQLConnection::ExecuteQueryEx( const char* queryStr, long iTimeout, int type ) { CMutexGuard guard(m_MutexQuery); if (m_iAutoConnect) { if (m_conn) { if ( PQstatus(m_conn) == CONNECTION_BAD ) { PQreset(m_conn); // 重试一次不行,就关闭该连接 if (PQstatus(m_conn) == CONNECTION_BAD) { PQfinish(m_conn); m_conn = NULL; } } } if (m_conn == NULL) { if ( !Connect(iTimeout) ) { return new PgSQLResult(-1, "连接出错"); } } } if (m_conn == NULL) { return new PgSQLResult(-1, "无数据库连接"); } PGresult* result = PQexec(m_conn, queryStr); if (result == NULL) { // 重试 Connect(iTimeout); result = PQexec(m_conn, queryStr); } if (result == NULL) { return NULL; } ExecStatusType resultInfo = PQresultStatus(result); m_errorCode = resultInfo; switch (resultInfo) { case PGRES_COMMAND_OK: // 仅记录影响行数 return new PgSQLResult( PQcmdTuples(result) ? atoi(PQcmdTuples(result)) : 0 ); break; case PGRES_TUPLES_OK: return new PgSQLResult(this, result); break; default: return new PgSQLResult(resultInfo, PQresultErrorMessage(result)); break; } }
static void BaseBackup(void) { PGresult *res; char *sysidentifier; uint32 timeline; char current_path[MAXPGPATH]; char escaped_label[MAXPGPATH]; int i; char xlogstart[64]; char xlogend[64]; /* * Connect in replication mode to the server */ conn = GetConnection(); /* * Run IDENTIFY_SYSTEM so we can get the timeline */ res = PQexec(conn, "IDENTIFY_SYSTEM"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, _("%s: could not identify system: %s\n"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (PQntuples(res) != 1 || PQnfields(res) != 3) { fprintf(stderr, _("%s: could not identify system, got %i rows and %i fields\n"), progname, PQntuples(res), PQnfields(res)); disconnect_and_exit(1); } sysidentifier = strdup(PQgetvalue(res, 0, 0)); timeline = atoi(PQgetvalue(res, 0, 1)); PQclear(res); /* * Start the actual backup */ PQescapeStringConn(conn, escaped_label, label, sizeof(escaped_label), &i); snprintf(current_path, sizeof(current_path), "BASE_BACKUP LABEL '%s' %s %s %s %s", escaped_label, showprogress ? "PROGRESS" : "", includewal && !streamwal ? "WAL" : "", fastcheckpoint ? "FAST" : "", includewal ? "NOWAIT" : ""); if (PQsendQuery(conn, current_path) == 0) { fprintf(stderr, _("%s: could not send base backup command: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } /* * Get the starting xlog position */ res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, _("%s: could not initiate base backup: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (PQntuples(res) != 1) { fprintf(stderr, _("%s: no start point returned from server\n"), progname); disconnect_and_exit(1); } strcpy(xlogstart, PQgetvalue(res, 0, 0)); if (verbose && includewal) fprintf(stderr, "xlog start point: %s\n", xlogstart); PQclear(res); MemSet(xlogend, 0, sizeof(xlogend)); /* * Get the header */ res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, _("%s: could not get backup header: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (PQntuples(res) < 1) { fprintf(stderr, _("%s: no data returned from server\n"), progname); disconnect_and_exit(1); } /* * Sum up the total size, for progress reporting */ totalsize = totaldone = 0; tablespacecount = PQntuples(res); for (i = 0; i < PQntuples(res); i++) { if (showprogress) totalsize += atol(PQgetvalue(res, i, 2)); /* * Verify tablespace directories are empty. Don't bother with the * first once since it can be relocated, and it will be checked before * we do anything anyway. */ if (format == 'p' && !PQgetisnull(res, i, 1)) verify_dir_is_empty_or_create(PQgetvalue(res, i, 1)); } /* * When writing to stdout, require a single tablespace */ if (format == 't' && strcmp(basedir, "-") == 0 && PQntuples(res) > 1) { fprintf(stderr, _("%s: can only write single tablespace to stdout, database has %d\n"), progname, PQntuples(res)); disconnect_and_exit(1); } /* * If we're streaming WAL, start the streaming session before we start * receiving the actual data chunks. */ if (streamwal) { if (verbose) fprintf(stderr, _("%s: starting background WAL receiver\n"), progname); StartLogStreamer(xlogstart, timeline, sysidentifier); } /* * Start receiving chunks */ for (i = 0; i < PQntuples(res); i++) { if (format == 't') ReceiveTarFile(conn, res, i); else ReceiveAndUnpackTarFile(conn, res, i); } /* Loop over all tablespaces */ if (showprogress) { progress_report(PQntuples(res), NULL); fprintf(stderr, "\n"); /* Need to move to next line */ } PQclear(res); /* * Get the stop position */ res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, _("%s: could not get WAL end position from server\n"), progname); disconnect_and_exit(1); } if (PQntuples(res) != 1) { fprintf(stderr, _("%s: no WAL end position returned from server\n"), progname); disconnect_and_exit(1); } strcpy(xlogend, PQgetvalue(res, 0, 0)); if (verbose && includewal) fprintf(stderr, "xlog end point: %s\n", xlogend); PQclear(res); res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, _("%s: final receive failed: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (bgchild > 0) { #ifndef WIN32 int status; int r; #else DWORD status; #endif if (verbose) fprintf(stderr, _("%s: waiting for background process to finish streaming...\n"), progname); #ifndef WIN32 if (pipewrite(bgpipe[1], xlogend, strlen(xlogend)) != strlen(xlogend)) { fprintf(stderr, _("%s: could not send command to background pipe: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } /* Just wait for the background process to exit */ r = waitpid(bgchild, &status, 0); if (r == -1) { fprintf(stderr, _("%s: could not wait for child process: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } if (r != bgchild) { fprintf(stderr, _("%s: child %i died, expected %i\n"), progname, r, bgchild); disconnect_and_exit(1); } if (!WIFEXITED(status)) { fprintf(stderr, _("%s: child process did not exit normally\n"), progname); disconnect_and_exit(1); } if (WEXITSTATUS(status) != 0) { fprintf(stderr, _("%s: child process exited with error %i\n"), progname, WEXITSTATUS(status)); disconnect_and_exit(1); } /* Exited normally, we're happy! */ #else /* WIN32 */ /* * On Windows, since we are in the same process, we can just store the * value directly in the variable, and then set the flag that says * it's there. */ if (sscanf(xlogend, "%X/%X", &xlogendptr.xlogid, &xlogendptr.xrecoff) != 2) { fprintf(stderr, _("%s: could not parse xlog end position \"%s\"\n"), progname, xlogend); disconnect_and_exit(1); } InterlockedIncrement(&has_xlogendptr); /* First wait for the thread to exit */ if (WaitForSingleObjectEx((HANDLE) bgchild, INFINITE, FALSE) != WAIT_OBJECT_0) { _dosmaperr(GetLastError()); fprintf(stderr, _("%s: could not wait for child thread: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } if (GetExitCodeThread((HANDLE) bgchild, &status) == 0) { _dosmaperr(GetLastError()); fprintf(stderr, _("%s: could not get child thread exit status: %s\n"), progname, strerror(errno)); disconnect_and_exit(1); } if (status != 0) { fprintf(stderr, _("%s: child thread exited with error %u\n"), progname, (unsigned int) status); disconnect_and_exit(1); } /* Exited normally, we're happy */ #endif } /* * End of copy data. Final result is already checked inside the loop. */ PQclear(res); PQfinish(conn); if (verbose) fprintf(stderr, "%s: base backup completed\n", progname); }
void Plugin::saveValue(const char *tagname, const char *tablename, const char *valstring) { #ifdef WITHDB PGconn *conn = NULL; TObject *dummy=getMemoryObject("Runnumber"); int runnumber=htonl(*(int*) &dummy); //ugly but works // Make a connection to the database conn = PQconnectdb("user=runinfo password=runinfo dbname=runinfo host=CookerWorkerNodeLNS00"); // Check to see that the backend connection was successfully made if (PQstatus(conn) != CONNECTION_OK) { debug(0,"Connection to database failed\n"); PQfinish(conn); return ; } const char *params[]={tagname,(char *) &runnumber,valstring}; int lengths[3]={strlen(tagname),sizeof(runnumber),strlen(valstring)}; int binary[3]={0,1,0}; debug(100,"Connection to database - OK\n"); PGresult *res=PQexecParams(conn, "select tagid from tagnames where tagname=$1::varchar;",1,NULL,params,lengths,binary,0); if (PQresultStatus(res) != PGRES_TUPLES_OK) { debug(0, "select tagid command failed: %s\n", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return; } debug(100,"Found %i\n",PQntuples(res)); if (PQntuples(res)==0) { PQclear(res); debug(100,"Trying to insert\n"); res=PQexecParams(conn, "insert into tagnames (tagname) values ($1::varchar);",1,NULL,params,lengths,binary,0); if (PQresultStatus(res) != PGRES_COMMAND_OK) { debug(0, "insert into tagid command failed: %s\n", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return; } } PQclear(res); debug(100,"Trying to insert\n"); char command[1000]; sprintf(command,"insert into %s (timestamp,runid,tagid,value) select now(),$2::int4,tagid,$3::double precision from tagnames where tagname=$1::varchar;",tablename); res=PQexecParams(conn, command,3,NULL,params,lengths,binary,0); if (PQresultStatus(res) != PGRES_COMMAND_OK) { debug(100, "insert into rundata command failed: %s\n Trying update", PQerrorMessage(conn)); PQclear(res); sprintf(command,"update %s set timestamp=now(), value=$3::double precision where runid=$2::int4 and tagid=(select tagid from tagnames where tagname=$1::varchar);",tablename); res=PQexecParams(conn, command,3,NULL,params,lengths,binary,0); if (PQresultStatus(res) != PGRES_COMMAND_OK) { debug(100, "update failed too: %s\n", PQerrorMessage(conn)); PQclear(res); PQfinish(conn); return; } } PQclear(res); PQfinish(conn); #else debug(10000,"DB not compiled in\n"); #endif }
/* * Receive a tar format stream from the connection to the server, and unpack * the contents of it into a directory. Only files, directories and * symlinks are supported, no other kinds of special files. * * If the data is for the main data directory, it will be restored in the * specified directory. If it's for another tablespace, it will be restored * in the original directory, since relocation of tablespaces is not * supported. */ static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum) { char current_path[MAXPGPATH]; char filename[MAXPGPATH]; int current_len_left; int current_padding = 0; char *copybuf = NULL; FILE *file = NULL; if (PQgetisnull(res, rownum, 0)) strcpy(current_path, basedir); else strcpy(current_path, PQgetvalue(res, rownum, 1)); /* * Get the COPY data */ res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_COPY_OUT) { fprintf(stderr, _("%s: could not get COPY data stream: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } while (1) { int r; if (copybuf != NULL) { PQfreemem(copybuf); copybuf = NULL; } r = PQgetCopyData(conn, ©buf, 0); if (r == -1) { /* * End of chunk */ if (file) fclose(file); break; } else if (r == -2) { fprintf(stderr, _("%s: could not read COPY data: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (file == NULL) { int filemode; /* * No current file, so this must be the header for a new file */ if (r != 512) { fprintf(stderr, _("%s: invalid tar block header size: %d\n"), progname, r); disconnect_and_exit(1); } totaldone += 512; if (sscanf(copybuf + 124, "%11o", ¤t_len_left) != 1) { fprintf(stderr, _("%s: could not parse file size\n"), progname); disconnect_and_exit(1); } /* Set permissions on the file */ if (sscanf(©buf[100], "%07o ", &filemode) != 1) { fprintf(stderr, _("%s: could not parse file mode\n"), progname); disconnect_and_exit(1); } /* * All files are padded up to 512 bytes */ current_padding = ((current_len_left + 511) & ~511) - current_len_left; /* * First part of header is zero terminated filename */ snprintf(filename, sizeof(filename), "%s/%s", current_path, copybuf); if (filename[strlen(filename) - 1] == '/') { /* * Ends in a slash means directory or symlink to directory */ if (copybuf[156] == '5') { /* * Directory */ filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */ if (mkdir(filename, S_IRWXU) != 0) { /* * When streaming WAL, pg_xlog will have been created * by the wal receiver process, so just ignore failure * on that. */ if (!streamwal || strcmp(filename + strlen(filename) - 8, "/pg_xlog") != 0) { fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } } #ifndef WIN32 if (chmod(filename, (mode_t) filemode)) fprintf(stderr, _("%s: could not set permissions on directory \"%s\": %s\n"), progname, filename, strerror(errno)); #endif } else if (copybuf[156] == '2') { /* * Symbolic link */ filename[strlen(filename) - 1] = '\0'; /* Remove trailing slash */ if (symlink(©buf[157], filename) != 0) { fprintf(stderr, _("%s: could not create symbolic link from \"%s\" to \"%s\": %s\n"), progname, filename, ©buf[157], strerror(errno)); disconnect_and_exit(1); } } else { fprintf(stderr, _("%s: unrecognized link indicator \"%c\"\n"), progname, copybuf[156]); disconnect_and_exit(1); } continue; /* directory or link handled */ } /* * regular file */ file = fopen(filename, "wb"); if (!file) { fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } #ifndef WIN32 if (chmod(filename, (mode_t) filemode)) fprintf(stderr, _("%s: could not set permissions on file \"%s\": %s\n"), progname, filename, strerror(errno)); #endif if (current_len_left == 0) { /* * Done with this file, next one will be a new tar header */ fclose(file); file = NULL; continue; } } /* new file */ else { /* * Continuing blocks in existing file */ if (current_len_left == 0 && r == current_padding) { /* * Received the padding block for this file, ignore it and * close the file, then move on to the next tar header. */ fclose(file); file = NULL; totaldone += r; continue; } if (fwrite(copybuf, r, 1, file) != 1) { fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } totaldone += r; if (showprogress) progress_report(rownum, filename); current_len_left -= r; if (current_len_left == 0 && current_padding == 0) { /* * Received the last block, and there is no padding to be * expected. Close the file and move on to the next tar * header. */ fclose(file); file = NULL; continue; } } /* continuing data in existing file */ } /* loop over all data blocks */ if (file != NULL) { fprintf(stderr, _("%s: COPY stream ended before last file was finished\n"), progname); disconnect_and_exit(1); } if (copybuf != NULL) PQfreemem(copybuf); }
/* * Receive a tar format file from the connection to the server, and write * the data from this file directly into a tar file. If compression is * enabled, the data will be compressed while written to the file. * * The file will be named base.tar[.gz] if it's for the main data directory * or <tablespaceoid>.tar[.gz] if it's for another tablespace. * * No attempt to inspect or validate the contents of the file is done. */ static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum) { char filename[MAXPGPATH]; char *copybuf = NULL; FILE *tarfile = NULL; #ifdef HAVE_LIBZ gzFile ztarfile = NULL; #endif if (PQgetisnull(res, rownum, 0)) /* * Base tablespaces */ if (strcmp(basedir, "-") == 0) { #ifdef HAVE_LIBZ if (compresslevel != 0) { ztarfile = gzdopen(dup(fileno(stdout)), "wb"); if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) { fprintf(stderr, _("%s: could not set compression level %d: %s\n"), progname, compresslevel, get_gz_error(ztarfile)); disconnect_and_exit(1); } } else #endif tarfile = stdout; } else { #ifdef HAVE_LIBZ if (compresslevel != 0) { snprintf(filename, sizeof(filename), "%s/base.tar.gz", basedir); ztarfile = gzopen(filename, "wb"); if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) { fprintf(stderr, _("%s: could not set compression level %d: %s\n"), progname, compresslevel, get_gz_error(ztarfile)); disconnect_and_exit(1); } } else #endif { snprintf(filename, sizeof(filename), "%s/base.tar", basedir); tarfile = fopen(filename, "wb"); } } else { /* * Specific tablespace */ #ifdef HAVE_LIBZ if (compresslevel != 0) { snprintf(filename, sizeof(filename), "%s/%s.tar.gz", basedir, PQgetvalue(res, rownum, 0)); ztarfile = gzopen(filename, "wb"); if (gzsetparams(ztarfile, compresslevel, Z_DEFAULT_STRATEGY) != Z_OK) { fprintf(stderr, _("%s: could not set compression level %d: %s\n"), progname, compresslevel, get_gz_error(ztarfile)); disconnect_and_exit(1); } } else #endif { snprintf(filename, sizeof(filename), "%s/%s.tar", basedir, PQgetvalue(res, rownum, 0)); tarfile = fopen(filename, "wb"); } } #ifdef HAVE_LIBZ if (compresslevel != 0) { if (!ztarfile) { /* Compression is in use */ fprintf(stderr, _("%s: could not create compressed file \"%s\": %s\n"), progname, filename, get_gz_error(ztarfile)); disconnect_and_exit(1); } } else #endif { /* Either no zlib support, or zlib support but compresslevel = 0 */ if (!tarfile) { fprintf(stderr, _("%s: could not create file \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } } /* * Get the COPY data stream */ res = PQgetResult(conn); if (PQresultStatus(res) != PGRES_COPY_OUT) { fprintf(stderr, _("%s: could not get COPY data stream: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } while (1) { int r; if (copybuf != NULL) { PQfreemem(copybuf); copybuf = NULL; } r = PQgetCopyData(conn, ©buf, 0); if (r == -1) { /* * End of chunk. Close file (but not stdout). * * Also, write two completely empty blocks at the end of the tar * file, as required by some tar programs. */ char zerobuf[1024]; MemSet(zerobuf, 0, sizeof(zerobuf)); #ifdef HAVE_LIBZ if (ztarfile != NULL) { if (gzwrite(ztarfile, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf)) { fprintf(stderr, _("%s: could not write to compressed file \"%s\": %s\n"), progname, filename, get_gz_error(ztarfile)); } } else #endif { if (fwrite(zerobuf, sizeof(zerobuf), 1, tarfile) != 1) { fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } } if (strcmp(basedir, "-") == 0) { #ifdef HAVE_LIBZ if (ztarfile) gzclose(ztarfile); #endif } else { #ifdef HAVE_LIBZ if (ztarfile != NULL) gzclose(ztarfile); #endif if (tarfile != NULL) fclose(tarfile); } break; } else if (r == -2) { fprintf(stderr, _("%s: could not read COPY data: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } #ifdef HAVE_LIBZ if (ztarfile != NULL) { if (gzwrite(ztarfile, copybuf, r) != r) { fprintf(stderr, _("%s: could not write to compressed file \"%s\": %s\n"), progname, filename, get_gz_error(ztarfile)); } } else #endif { if (fwrite(copybuf, r, 1, tarfile) != 1) { fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), progname, filename, strerror(errno)); disconnect_and_exit(1); } } totaldone += r; if (showprogress) progress_report(rownum, filename); } /* while (1) */ if (copybuf != NULL) PQfreemem(copybuf); }
/****************************************************************************** * * * Function: zbx_db_vselect * * * * Purpose: execute a select statement * * * * Return value: data, NULL (on error) or (DB_RESULT)ZBX_DB_DOWN * * * ******************************************************************************/ DB_RESULT zbx_db_vselect(const char *fmt, va_list args) { char *sql = NULL; DB_RESULT result = NULL; double sec = 0; #if defined(HAVE_IBM_DB2) int i; SQLRETURN ret = SQL_SUCCESS; #elif defined(HAVE_ORACLE) sword err = OCI_SUCCESS; ub4 counter; #elif defined(HAVE_POSTGRESQL) char *error = NULL; #elif defined(HAVE_SQLITE3) int ret = FAIL; char *error = NULL; #endif if (CONFIG_LOG_SLOW_QUERIES) sec = zbx_time(); sql = zbx_dvsprintf(sql, fmt, args); zabbix_log(LOG_LEVEL_DEBUG, "query [txnlev:%d] [%s]", txn_level, sql); #if defined(HAVE_IBM_DB2) result = zbx_malloc(result, sizeof(ZBX_IBM_DB2_RESULT)); memset(result, 0, sizeof(ZBX_IBM_DB2_RESULT)); /* allocate a statement handle */ if (SUCCEED != zbx_ibm_db2_success(ret = SQLAllocHandle(SQL_HANDLE_STMT, ibm_db2.hdbc, &result->hstmt))) goto error; /* directly execute the statement */ if (SUCCEED != zbx_ibm_db2_success(ret = SQLExecDirect(result->hstmt, (SQLCHAR *)sql, SQL_NTS))) goto error; /* identify the number of output columns */ if (SUCCEED != zbx_ibm_db2_success(ret = SQLNumResultCols(result->hstmt, &result->ncolumn))) goto error; if (0 == result->ncolumn) goto error; result->nalloc = 0; result->values = zbx_malloc(result->values, sizeof(char *) * result->ncolumn); result->values_cli = zbx_malloc(result->values_cli, sizeof(char *) * result->ncolumn); result->values_len = zbx_malloc(result->values_len, sizeof(SQLINTEGER) * result->ncolumn); for (i = 0; i < result->ncolumn; i++) { /* get the display size for a column */ if (SUCCEED != zbx_ibm_db2_success(ret = SQLColAttribute(result->hstmt, (SQLSMALLINT)(i + 1), SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &result->values_len[i]))) { goto error; } result->values_len[i] += 1; /* '\0'; */ /* allocate memory to bind a column */ result->values_cli[i] = zbx_malloc(NULL, result->values_len[i]); result->nalloc++; /* bind columns to program variables, converting all types to CHAR */ if (SUCCEED != zbx_ibm_db2_success(ret = SQLBindCol(result->hstmt, (SQLSMALLINT)(i + 1), SQL_C_CHAR, result->values_cli[i], result->values_len[i], &result->values_len[i]))) { goto error; } } error: if (SUCCEED != zbx_ibm_db2_success(ret) || 0 == result->ncolumn) { zbx_ibm_db2_log_errors(SQL_HANDLE_DBC, ibm_db2.hdbc); zbx_ibm_db2_log_errors(SQL_HANDLE_STMT, result->hstmt); IBM_DB2free_result(result); result = (SQL_CD_TRUE == IBM_DB2server_status() ? NULL : (DB_RESULT)ZBX_DB_DOWN); } #elif defined(HAVE_MYSQL) if (NULL == conn) { zabbix_errlog(ERR_Z3003); result = NULL; } else { if (0 != mysql_query(conn, sql)) { zabbix_errlog(ERR_Z3005, mysql_errno(conn), mysql_error(conn), sql); switch (mysql_errno(conn)) { case CR_CONN_HOST_ERROR: case CR_SERVER_GONE_ERROR: case CR_CONNECTION_ERROR: case CR_SERVER_LOST: case ER_SERVER_SHUTDOWN: case ER_ACCESS_DENIED_ERROR: /* wrong user or password */ case ER_ILLEGAL_GRANT_FOR_TABLE: /* user without any privileges */ case ER_TABLEACCESS_DENIED_ERROR:/* user without some privilege */ case ER_UNKNOWN_ERROR: result = (DB_RESULT)ZBX_DB_DOWN; break; default: result = NULL; break; } } else result = mysql_store_result(conn); } #elif defined(HAVE_ORACLE) result = zbx_malloc(NULL, sizeof(ZBX_OCI_DB_RESULT)); memset(result, 0, sizeof(ZBX_OCI_DB_RESULT)); err = OCIHandleAlloc((dvoid *)oracle.envhp, (dvoid **)&result->stmthp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0); if (OCI_SUCCESS == err) { err = OCIStmtPrepare(result->stmthp, oracle.errhp, (text *)sql, (ub4)strlen((char *)sql), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT); } if (OCI_SUCCESS == err) { err = OCIStmtExecute(oracle.svchp, result->stmthp, oracle.errhp, (ub4)0, (ub4)0, (CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, OCI_COMMIT_ON_SUCCESS); } if (OCI_SUCCESS == err) { /* get the number of columns in the query */ err = OCIAttrGet((void *)result->stmthp, OCI_HTYPE_STMT, (void *)&result->ncolumn, (ub4 *)0, OCI_ATTR_PARAM_COUNT, oracle.errhp); } if (OCI_SUCCESS != err) goto error; assert(0 < result->ncolumn); result->values = zbx_malloc(NULL, result->ncolumn * sizeof(char *)); memset(result->values, 0, result->ncolumn * sizeof(char *)); for (counter = 1; OCI_SUCCESS == err && counter <= result->ncolumn; counter++) { OCIParam *parmdp = NULL; OCIDefine *defnp = NULL; ub4 char_semantics; ub2 col_width; /* request a parameter descriptor in the select-list */ err = OCIParamGet((void *)result->stmthp, OCI_HTYPE_STMT, oracle.errhp, (void **)&parmdp, (ub4)counter); if (OCI_SUCCESS == err) { /* retrieve the length semantics for the column */ char_semantics = 0; err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&char_semantics, (ub4 *)0, (ub4)OCI_ATTR_CHAR_USED, (OCIError *)oracle.errhp); } if (OCI_SUCCESS == err) { col_width = 0; if (char_semantics) { /* retrieve the column width in characters */ err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&col_width, (ub4 *)0, (ub4)OCI_ATTR_CHAR_SIZE, (OCIError *)oracle.errhp); } else { /* retrieve the column width in bytes */ err = OCIAttrGet((void *)parmdp, (ub4)OCI_DTYPE_PARAM, (void *)&col_width, (ub4 *)0, (ub4)OCI_ATTR_DATA_SIZE, (OCIError *)oracle.errhp); } } col_width++; result->values[counter - 1] = zbx_malloc(NULL, col_width); memset(result->values[counter - 1], 0, col_width); if (OCI_SUCCESS == err) { /* represent any data as characters */ err = OCIDefineByPos(result->stmthp, &defnp, oracle.errhp, counter, (dvoid *)result->values[counter - 1], col_width, SQLT_STR, (dvoid *)0, (ub2 *)0, (ub2 *)0, OCI_DEFAULT); } /* free cell descriptor */ OCIDescriptorFree(parmdp, OCI_DTYPE_PARAM); parmdp = NULL; } error: if (OCI_SUCCESS != err) { zabbix_errlog(ERR_Z3005, err, zbx_oci_error(err), sql); OCI_DBfree_result(result); result = (OCI_SERVER_NORMAL == OCI_DBserver_status() ? NULL : (DB_RESULT)ZBX_DB_DOWN); } #elif defined(HAVE_POSTGRESQL) result = zbx_malloc(NULL, sizeof(ZBX_PG_DB_RESULT)); result->pg_result = PQexec(conn, sql); result->values = NULL; result->cursor = 0; result->row_num = 0; if (NULL == result->pg_result) zabbix_errlog(ERR_Z3005, 0, "result is NULL", sql); if (PGRES_TUPLES_OK != PQresultStatus(result->pg_result)) { error = zbx_dsprintf(error, "%s:%s", PQresStatus(PQresultStatus(result->pg_result)), PQresultErrorMessage(result->pg_result)); zabbix_errlog(ERR_Z3005, 0, error, sql); zbx_free(error); PG_DBfree_result(result); result = (CONNECTION_OK == PQstatus(conn) ? NULL : (DB_RESULT)ZBX_DB_DOWN); } else /* init rownum */ result->row_num = PQntuples(result->pg_result); #elif defined(HAVE_SQLITE3) if (0 == txn_level && PHP_MUTEX_OK != php_sem_acquire(&sqlite_access)) { zabbix_log(LOG_LEVEL_CRIT, "ERROR: unable to create lock on SQLite database"); exit(FAIL); } result = zbx_malloc(NULL, sizeof(ZBX_SQ_DB_RESULT)); result->curow = 0; lbl_get_table: if (SQLITE_OK != (ret = sqlite3_get_table(conn,sql, &result->data, &result->nrow, &result->ncolumn, &error))) { if (SQLITE_BUSY == ret) goto lbl_get_table; zabbix_errlog(ERR_Z3005, 0, error, sql); sqlite3_free(error); SQ_DBfree_result(result); switch (ret) { case SQLITE_ERROR: /* SQL error or missing database; assuming SQL error, because if we are this far into execution, zbx_db_connect() was successful */ case SQLITE_NOMEM: /* a malloc() failed */ case SQLITE_MISMATCH: /* data type mismatch */ result = NULL; break; default: result = (DB_RESULT)ZBX_DB_DOWN; break; } } if (0 == txn_level) php_sem_release(&sqlite_access); #endif /* HAVE_SQLITE3 */ if (CONFIG_LOG_SLOW_QUERIES) { sec = zbx_time() - sec; if (sec > (double)CONFIG_LOG_SLOW_QUERIES / 1000.0) zabbix_log(LOG_LEVEL_WARNING, "slow query: " ZBX_FS_DBL " sec, \"%s\"", sec, sql); } zbx_free(sql); return result; }
/************************************************************************* * * Function: sql_query * * Purpose: Issue a query to the database * *************************************************************************/ static sql_rcode_t sql_query(rlm_sql_handle_t * handle, UNUSED rlm_sql_config_t *config, char const *query) { rlm_sql_postgres_conn_t *conn = handle->conn; int numfields = 0; char *errorcode; char *errormsg; if (!conn->db) { ERROR("rlm_sql_postgresql: Socket not connected"); return RLM_SQL_RECONNECT; } conn->result = PQexec(conn->db, query); /* * Returns a PGresult pointer or possibly a null pointer. * A non-null pointer will generally be returned except in * out-of-memory conditions or serious errors such as inability * to send the command to the server. If a null pointer is * returned, it should be treated like a PGRES_FATAL_ERROR * result. */ if (!conn->result) { ERROR("rlm_sql_postgresql: PostgreSQL Query failed Error: %s", PQerrorMessage(conn->db)); /* As this error COULD be a connection error OR an out-of-memory * condition return value WILL be wrong SOME of the time regardless! * Pick your poison.... */ return RLM_SQL_RECONNECT; } else { ExecStatusType status = PQresultStatus(conn->result); DEBUG("rlm_sql_postgresql: Status: %s", PQresStatus(status)); switch (status){ case PGRES_COMMAND_OK: /*Successful completion of a command returning no data.*/ /*affected_rows function only returns the number of affected rows of a command returning no data... */ conn->affected_rows = affected_rows(conn->result); DEBUG("rlm_sql_postgresql: query affected rows = %i", conn->affected_rows); return 0; break; case PGRES_TUPLES_OK: /*Successful completion of a command returning data (such as a SELECT or SHOW).*/ conn->cur_row = 0; conn->affected_rows = PQntuples(conn->result); numfields = PQnfields(conn->result); /*Check row storing functions..*/ DEBUG("rlm_sql_postgresql: query affected rows = %i , fields = %i", conn->affected_rows, numfields); return 0; break; case PGRES_BAD_RESPONSE: /*The server's response was not understood.*/ DEBUG("rlm_sql_postgresql: Bad Response From Server!!"); return -1; break; case PGRES_NONFATAL_ERROR: /*A nonfatal error (a notice or warning) occurred. Possibly never returns*/ return -1; break; case PGRES_FATAL_ERROR: #if defined(PG_DIAG_SQLSTATE) && defined(PG_DIAG_MESSAGE_PRIMARY) /*A fatal error occurred.*/ errorcode = PQresultErrorField(conn->result, PG_DIAG_SQLSTATE); errormsg = PQresultErrorField(conn->result, PG_DIAG_MESSAGE_PRIMARY); DEBUG("rlm_sql_postgresql: Error %s", errormsg); return check_fatal_error(errorcode); #endif break; default: /* FIXME: An unhandled error occurred.*/ /* PGRES_EMPTY_QUERY PGRES_COPY_OUT PGRES_COPY_IN */ return -1; break; } /* Note to self ... sql_store_result returns 0 anyway after setting the handle->affected_rows.. sql_num_fields returns 0 at worst case which means the check below has a really small chance to return false.. lets remove it then .. yuck!! */ /* } else { if ((sql_store_result(handle, config) == 0) && (sql_num_fields(handle, config) >= 0)) return 0; else return -1; } */ } return -1; }
/* * ExecQueryUsingCursor: run a SELECT-like query using a cursor * * This feature allows result sets larger than RAM to be dealt with. * * Returns true if the query executed successfully, false otherwise. * * If pset.timing is on, total query time (exclusive of result-printing) is * stored into *elapsed_msec. */ static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec) { bool OK = true; PGresult *results; PQExpBufferData buf; printQueryOpt my_popt = pset.popt; FILE *queryFout_copy = pset.queryFout; bool queryFoutPipe_copy = pset.queryFoutPipe; bool started_txn = false; bool did_pager = false; int ntuples; int fetch_count; char fetch_cmd[64]; instr_time before, after; int flush_error; *elapsed_msec = 0; /* initialize print options for partial table output */ my_popt.topt.start_table = true; my_popt.topt.stop_table = false; my_popt.topt.prior_records = 0; if (pset.timing) INSTR_TIME_SET_CURRENT(before); /* if we're not in a transaction, start one */ if (PQtransactionStatus(pset.db) == PQTRANS_IDLE) { results = PQexec(pset.db, "BEGIN"); OK = AcceptResult(results) && (PQresultStatus(results) == PGRES_COMMAND_OK); PQclear(results); if (!OK) return false; started_txn = true; } /* Send DECLARE CURSOR */ initPQExpBuffer(&buf); appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s", query); results = PQexec(pset.db, buf.data); OK = AcceptResult(results) && (PQresultStatus(results) == PGRES_COMMAND_OK); PQclear(results); termPQExpBuffer(&buf); if (!OK) goto cleanup; if (pset.timing) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); } /* * In \gset mode, we force the fetch count to be 2, so that we will throw * the appropriate error if the query returns more than one row. */ if (pset.gset_prefix) fetch_count = 2; else fetch_count = pset.fetch_count; snprintf(fetch_cmd, sizeof(fetch_cmd), "FETCH FORWARD %d FROM _psql_cursor", fetch_count); /* prepare to write output to \g argument, if any */ if (pset.gfname) { /* keep this code in sync with PrintQueryTuples */ pset.queryFout = stdout; /* so it doesn't get closed */ /* open file/pipe */ if (!setQFout(pset.gfname)) { pset.queryFout = queryFout_copy; pset.queryFoutPipe = queryFoutPipe_copy; OK = false; goto cleanup; } } /* clear any pre-existing error indication on the output stream */ clearerr(pset.queryFout); for (;;) { if (pset.timing) INSTR_TIME_SET_CURRENT(before); /* get fetch_count tuples at a time */ results = PQexec(pset.db, fetch_cmd); if (pset.timing) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); } if (PQresultStatus(results) != PGRES_TUPLES_OK) { /* shut down pager before printing error message */ if (did_pager) { ClosePager(pset.queryFout); pset.queryFout = queryFout_copy; pset.queryFoutPipe = queryFoutPipe_copy; did_pager = false; } OK = AcceptResult(results); Assert(!OK); PQclear(results); break; } if (pset.gset_prefix) { /* StoreQueryTuple will complain if not exactly one row */ OK = StoreQueryTuple(results); PQclear(results); break; } ntuples = PQntuples(results); if (ntuples < fetch_count) { /* this is the last result set, so allow footer decoration */ my_popt.topt.stop_table = true; } else if (pset.queryFout == stdout && !did_pager) { /* * If query requires multiple result sets, hack to ensure that * only one pager instance is used for the whole mess */ pset.queryFout = PageOutput(100000, &(my_popt.topt)); did_pager = true; } printQuery(results, &my_popt, pset.queryFout, pset.logfile); PQclear(results); /* after the first result set, disallow header decoration */ my_popt.topt.start_table = false; my_popt.topt.prior_records += ntuples; /* * Make sure to flush the output stream, so intermediate results are * visible to the client immediately. We check the results because if * the pager dies/exits/etc, there's no sense throwing more data at * it. */ flush_error = fflush(pset.queryFout); /* * Check if we are at the end, if a cancel was pressed, or if there * were any errors either trying to flush out the results, or more * generally on the output stream at all. If we hit any errors * writing things to the stream, we presume $PAGER has disappeared and * stop bothering to pull down more data. */ if (ntuples < fetch_count || cancel_pressed || flush_error || ferror(pset.queryFout)) break; } /* close \g argument file/pipe, restore old setting */ if (pset.gfname) { /* keep this code in sync with PrintQueryTuples */ setQFout(NULL); pset.queryFout = queryFout_copy; pset.queryFoutPipe = queryFoutPipe_copy; } else if (did_pager) { ClosePager(pset.queryFout); pset.queryFout = queryFout_copy; pset.queryFoutPipe = queryFoutPipe_copy; } cleanup: if (pset.timing) INSTR_TIME_SET_CURRENT(before); /* * We try to close the cursor on either success or failure, but on failure * ignore the result (it's probably just a bleat about being in an aborted * transaction) */ results = PQexec(pset.db, "CLOSE _psql_cursor"); if (OK) { OK = AcceptResult(results) && (PQresultStatus(results) == PGRES_COMMAND_OK); } PQclear(results); if (started_txn) { results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK"); OK &= AcceptResult(results) && (PQresultStatus(results) == PGRES_COMMAND_OK); PQclear(results); } if (pset.timing) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); } return OK; }
/* * Generate a new buffer id supposed to be unique for a given layer name */ buffer *ows_psql_generate_id(ows * o, buffer * layer_name) { ows_layer_node *ln; buffer * id, *sql_id; FILE *fp; PGresult * res; int i, seed_len; char * seed = NULL; assert(o); assert(o->layers); assert(layer_name); /* Retrieve layer node pointer */ for (ln = o->layers->first ; ln ; ln = ln->next) { if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf)) break; } assert(ln); id = buffer_init(); /* If PK have a sequence in PostgreSQL database, * retrieve next available sequence value */ if (ln->layer->storage->pkey_sequence) { sql_id = buffer_init(); buffer_add_str(sql_id, "SELECT nextval('"); buffer_copy(sql_id, ln->layer->storage->pkey_sequence); buffer_add_str(sql_id, "');"); res = ows_psql_exec(o, sql_id->buf); buffer_free(sql_id); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) { buffer_add_str(id, (char *) PQgetvalue(res, 0, 0)); PQclear(res); return id; } /* FIXME: Shouldn't we return an error there instead ? */ PQclear(res); } /* * If we don't have a PostgreSQL Sequence, we will try to * generate a pseudo random keystring using /dev/urandom * Will so work only on somes/commons Unix system */ seed_len = 6; seed = malloc(sizeof(char) * (seed_len * 3 + 1)); /* multiply by 3 to be able to deal with hex2dec conversion */ assert(seed); seed[0] = '\0'; fp = fopen("/dev/urandom","r"); if (fp) { for (i=0 ; i<seed_len ; i++) sprintf(seed,"%s%03d", seed, fgetc(fp)); fclose(fp); buffer_add_str(id, seed); free(seed); return id; } free(seed); /* Case where we not using PostgreSQL sequence, * and OS don't have a /dev/urandom support * This case don't prevent to produce ID collision * Don't use it unless really no others choices !!! */ srand((int) (time(NULL) ^ rand() % 1000) + 42); srand((rand() % 1000 ^ rand() % 1000) + 42); buffer_add_int(id, rand()); return id; }
/* * PSQLexecWatch * * This function is used for \watch command to send the query to * the server and print out the results. * * Returns 1 if the query executed successfully, 0 if it cannot be repeated, * e.g., because of the interrupt, -1 on error. */ int PSQLexecWatch(const char *query, const printQueryOpt *opt) { PGresult *res; double elapsed_msec = 0; instr_time before; instr_time after; if (!pset.db) { psql_error("You are currently not connected to a database.\n"); return 0; } SetCancelConn(); if (pset.timing) INSTR_TIME_SET_CURRENT(before); res = PQexec(pset.db, query); ResetCancelConn(); if (!AcceptResult(res)) { PQclear(res); return 0; } if (pset.timing) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); elapsed_msec = INSTR_TIME_GET_MILLISEC(after); } /* * If SIGINT is sent while the query is processing, the interrupt * will be consumed. The user's intention, though, is to cancel * the entire watch process, so detect a sent cancellation request and * exit in this case. */ if (cancel_pressed) { PQclear(res); return 0; } switch (PQresultStatus(res)) { case PGRES_TUPLES_OK: printQuery(res, opt, pset.queryFout, pset.logfile); break; case PGRES_COMMAND_OK: fprintf(pset.queryFout, "%s\n%s\n\n", opt->title, PQcmdStatus(res)); break; case PGRES_EMPTY_QUERY: psql_error(_("\\watch cannot be used with an empty query\n")); PQclear(res); return -1; case PGRES_COPY_OUT: case PGRES_COPY_IN: case PGRES_COPY_BOTH: psql_error(_("\\watch cannot be used with COPY\n")); PQclear(res); return -1; default: psql_error(_("unexpected result status for \\watch\n")); PQclear(res); return -1; } PQclear(res); fflush(pset.queryFout); /* Possible microtiming output */ if (pset.timing) printf(_("Time: %.3f ms\n"), elapsed_msec); return 1; }
int main(int argc, char *argv[]) { static int if_exists = 0; static struct option long_options[] = { {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, {"no-password", no_argument, NULL, 'w'}, {"password", no_argument, NULL, 'W'}, {"echo", no_argument, NULL, 'e'}, {"interactive", no_argument, NULL, 'i'}, {"if-exists", no_argument, &if_exists, 1}, {"maintenance-db", required_argument, NULL, 2}, {NULL, 0, NULL, 0} }; const char *progname; int optindex; int c; char *dbname = NULL; char *maintenance_db = NULL; char *host = NULL; char *port = NULL; char *username = NULL; enum trivalue prompt_password = TRI_DEFAULT; bool echo = false; bool interactive = false; PQExpBufferData sql; PGconn *conn; PGresult *result; progname = get_progname(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts")); handle_help_version_opts(argc, argv, "dropdb", help); while ((c = getopt_long(argc, argv, "h:p:U:wWei", long_options, &optindex)) != -1) { switch (c) { case 'h': host = pg_strdup(optarg); break; case 'p': port = pg_strdup(optarg); break; case 'U': username = pg_strdup(optarg); break; case 'w': prompt_password = TRI_NO; break; case 'W': prompt_password = TRI_YES; break; case 'e': echo = true; break; case 'i': interactive = true; break; case 0: /* this covers the long options */ break; case 2: maintenance_db = pg_strdup(optarg); break; default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } } switch (argc - optind) { case 0: fprintf(stderr, _("%s: missing required argument database name\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); case 1: dbname = argv[optind]; break; default: fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind + 1]); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (interactive) { printf(_("Database \"%s\" will be permanently removed.\n"), dbname); if (!yesno_prompt("Are you sure?")) exit(0); } initPQExpBuffer(&sql); appendPQExpBuffer(&sql, "DROP DATABASE %s%s;", (if_exists ? "IF EXISTS " : ""), fmtId(dbname)); /* Avoid trying to drop postgres db while we are connected to it. */ if (maintenance_db == NULL && strcmp(dbname, "postgres") == 0) maintenance_db = "template1"; conn = connectMaintenanceDatabase(maintenance_db, host, port, username, prompt_password, progname, echo); if (echo) printf("%s\n", sql.data); result = PQexec(conn, sql.data); if (PQresultStatus(result) != PGRES_COMMAND_OK) { fprintf(stderr, _("%s: database removal failed: %s"), progname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } PQclear(result); PQfinish(conn); exit(0); }
/* * ProcessResult: utility function for use by SendQuery() only * * When our command string contained a COPY FROM STDIN or COPY TO STDOUT, * PQexec() has stopped at the PGresult associated with the first such * command. In that event, we'll marshal data for the COPY and then cycle * through any subsequent PGresult objects. * * When the command string contained no such COPY command, this function * degenerates to an AcceptResult() call. * * Changes its argument to point to the last PGresult of the command string, * or NULL if that result was for a COPY TO STDOUT. (Returning NULL prevents * the command status from being printed, which we want in that case so that * the status line doesn't get taken as part of the COPY data.) * * Returns true on complete success, false otherwise. Possible failure modes * include purely client-side problems; check the transaction status for the * server-side opinion. */ static bool ProcessResult(PGresult **results) { bool success = true; bool first_cycle = true; for (;;) { ExecStatusType result_status; bool is_copy; PGresult *next_result; if (!AcceptResult(*results)) { /* * Failure at this point is always a server-side failure or a * failure to submit the command string. Either way, we're * finished with this command string. */ success = false; break; } result_status = PQresultStatus(*results); switch (result_status) { case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: case PGRES_TUPLES_OK: is_copy = false; break; case PGRES_COPY_OUT: case PGRES_COPY_IN: is_copy = true; break; default: /* AcceptResult() should have caught anything else. */ is_copy = false; psql_error("unexpected PQresultStatus: %d\n", result_status); break; } if (is_copy) { /* * Marshal the COPY data. Either subroutine will get the * connection out of its COPY state, then call PQresultStatus() * once and report any error. * * If pset.copyStream is set, use that as data source/sink, * otherwise use queryFout or cur_cmd_source as appropriate. */ FILE *copystream = pset.copyStream; PGresult *copy_result; SetCancelConn(); if (result_status == PGRES_COPY_OUT) { if (!copystream) copystream = pset.queryFout; success = handleCopyOut(pset.db, copystream, ©_result) && success; /* * Suppress status printing if the report would go to the same * place as the COPY data just went. Note this doesn't * prevent error reporting, since handleCopyOut did that. */ if (copystream == pset.queryFout) { PQclear(copy_result); copy_result = NULL; } } else { if (!copystream) copystream = pset.cur_cmd_source; success = handleCopyIn(pset.db, copystream, PQbinaryTuples(*results), ©_result) && success; } ResetCancelConn(); /* * Replace the PGRES_COPY_OUT/IN result with COPY command's exit * status, or with NULL if we want to suppress printing anything. */ PQclear(*results); *results = copy_result; } else if (first_cycle) { /* fast path: no COPY commands; PQexec visited all results */ break; } /* * Check PQgetResult() again. In the typical case of a single-command * string, it will return NULL. Otherwise, we'll have other results * to process that may include other COPYs. We keep the last result. */ next_result = PQgetResult(pset.db); if (!next_result) break; PQclear(*results); *results = next_result; first_cycle = false; } /* may need this to recover from conn loss during COPY */ if (!first_cycle && !CheckConnection()) return false; return success; }
/* * Send a query and wait for the results by using the asynchronous libpq * functions and the backend version of select(). * * We must not use the regular blocking libpq functions like PQexec() * since they are uninterruptible by signals on some platforms, such as * Windows. * * We must also not use vanilla select() here since it cannot handle the * signal emulation layer on Windows. * * The function is modeled on PQexec() in libpq, but only implements * those parts that are in use in the walreceiver. * * Queries are always executed on the connection in streamConn. */ static PGresult * libpqrcv_PQexec(const char *query) { PGresult *result = NULL; PGresult *lastResult = NULL; /* * PQexec() silently discards any prior query results on the * connection. This is not required for walreceiver since it's * expected that walsender won't generate any such junk results. */ /* * Submit a query. Since we don't use non-blocking mode, this also * can block. But its risk is relatively small, so we ignore that * for now. */ if (!PQsendQuery(streamConn, query)) return NULL; for (;;) { /* * Receive data until PQgetResult is ready to get the result * without blocking. */ while (PQisBusy(streamConn)) { /* * We don't need to break down the sleep into smaller increments, * and check for interrupts after each nap, since we can just * elog(FATAL) within SIGTERM signal handler if the signal * arrives in the middle of establishment of replication connection. */ if (!libpq_select(-1)) continue; /* interrupted */ if (PQconsumeInput(streamConn) == 0) return NULL; /* trouble */ } /* * Emulate the PQexec()'s behavior of returning the last result * when there are many. * Since walsender will never generate multiple results, we skip * the concatenation of error messages. */ result = PQgetResult(streamConn); if (result == NULL) break; /* query is complete */ PQclear(lastResult); lastResult = result; if (PQresultStatus(lastResult) == PGRES_COPY_IN || PQresultStatus(lastResult) == PGRES_COPY_OUT || PQstatus(streamConn) == CONNECTION_BAD) break; } return lastResult; }
/* * SendQuery: send the query string to the backend * (and print out results) * * Note: This is the "front door" way to send a query. That is, use it to * send queries actually entered by the user. These queries will be subject to * single step mode. * To send "back door" queries (generated by slash commands, etc.) in a * controlled way, use PSQLexec(). * * Returns true if the query executed successfully, false otherwise. */ bool SendQuery(const char *query) { PGresult *results; PGTransactionStatusType transaction_status; double elapsed_msec = 0; bool OK = false; bool on_error_rollback_savepoint = false; static bool on_error_rollback_warning = false; if (!pset.db) { psql_error("You are currently not connected to a database.\n"); goto sendquery_cleanup; } if (pset.singlestep) { char buf[3]; printf(_("***(Single step mode: verify command)*******************************************\n" "%s\n" "***(press return to proceed or enter x and return to cancel)********************\n"), query); fflush(stdout); if (fgets(buf, sizeof(buf), stdin) != NULL) if (buf[0] == 'x') goto sendquery_cleanup; } else if (pset.echo == PSQL_ECHO_QUERIES) { puts(query); fflush(stdout); } if (pset.logfile) { fprintf(pset.logfile, _("********* QUERY **********\n" "%s\n" "**************************\n\n"), query); fflush(pset.logfile); } SetCancelConn(); transaction_status = PQtransactionStatus(pset.db); if (transaction_status == PQTRANS_IDLE && !pset.autocommit && !command_no_begin(query)) { results = PQexec(pset.db, "BEGIN"); if (PQresultStatus(results) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(pset.db)); PQclear(results); ResetCancelConn(); goto sendquery_cleanup; } PQclear(results); transaction_status = PQtransactionStatus(pset.db); } if (transaction_status == PQTRANS_INTRANS && pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF && (pset.cur_cmd_interactive || pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON)) { if (on_error_rollback_warning == false && pset.sversion < 80000) { psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n", pset.sversion / 10000, (pset.sversion / 100) % 100); on_error_rollback_warning = true; } else { results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint"); if (PQresultStatus(results) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(pset.db)); PQclear(results); ResetCancelConn(); goto sendquery_cleanup; } PQclear(results); on_error_rollback_savepoint = true; } } if (pset.fetch_count <= 0 || !is_select_command(query)) { /* Default fetch-it-all-and-print mode */ instr_time before, after; if (pset.timing) INSTR_TIME_SET_CURRENT(before); results = PQexec(pset.db, query); /* these operations are included in the timing result: */ ResetCancelConn(); OK = ProcessResult(&results); if (pset.timing) { INSTR_TIME_SET_CURRENT(after); INSTR_TIME_SUBTRACT(after, before); elapsed_msec = INSTR_TIME_GET_MILLISEC(after); } /* but printing results isn't: */ if (OK && results) OK = PrintQueryResults(results); } else { /* Fetch-in-segments mode */ OK = ExecQueryUsingCursor(query, &elapsed_msec); ResetCancelConn(); results = NULL; /* PQclear(NULL) does nothing */ } if (!OK && pset.echo == PSQL_ECHO_ERRORS) psql_error("STATEMENT: %s\n", query); /* If we made a temporary savepoint, possibly release/rollback */ if (on_error_rollback_savepoint) { const char *svptcmd = NULL; transaction_status = PQtransactionStatus(pset.db); switch (transaction_status) { case PQTRANS_INERROR: /* We always rollback on an error */ svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint"; break; case PQTRANS_IDLE: /* If they are no longer in a transaction, then do nothing */ break; case PQTRANS_INTRANS: /* * Do nothing if they are messing with savepoints themselves: * If the user did RELEASE or ROLLBACK, our savepoint is gone. * If they issued a SAVEPOINT, releasing ours would remove * theirs. */ if (results && (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 || strcmp(PQcmdStatus(results), "RELEASE") == 0 || strcmp(PQcmdStatus(results), "ROLLBACK") == 0)) svptcmd = NULL; else svptcmd = "RELEASE pg_psql_temporary_savepoint"; break; case PQTRANS_ACTIVE: case PQTRANS_UNKNOWN: default: OK = false; /* PQTRANS_UNKNOWN is expected given a broken connection. */ if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp()) psql_error("unexpected transaction status (%d)\n", transaction_status); break; } if (svptcmd) { PGresult *svptres; svptres = PQexec(pset.db, svptcmd); if (PQresultStatus(svptres) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(pset.db)); PQclear(svptres); OK = false; PQclear(results); ResetCancelConn(); goto sendquery_cleanup; } PQclear(svptres); } } PQclear(results); /* Possible microtiming output */ if (pset.timing) printf(_("Time: %.3f ms\n"), elapsed_msec); /* check for events that may occur during query execution */ if (pset.encoding != PQclientEncoding(pset.db) && PQclientEncoding(pset.db) >= 0) { /* track effects of SET CLIENT_ENCODING */ pset.encoding = PQclientEncoding(pset.db); pset.popt.topt.encoding = pset.encoding; SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); } PrintNotifications(); /* perform cleanup that should occur after any attempted query */ sendquery_cleanup: /* reset \g's output-to-filename trigger */ if (pset.gfname) { free(pset.gfname); pset.gfname = NULL; } /* reset \gset trigger */ if (pset.gset_prefix) { free(pset.gset_prefix); pset.gset_prefix = NULL; } return OK; }
int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; int nFields; int i, j; if (argc > 1) conninfo = argv[1]; else conninfo = "host=localhost port=5432 user=korisk dbname=test"; /* Make a connection to the database */ conn = PQconnectdb(conninfo); /* Check to see that the backend connection was successfully made */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); exit_nicely(conn); } /* Start a transaction block */ res = PQexec(conn, "BEGIN"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); /* * * Should PQclear PGresult whenever it is no longer needed to avoid memory * * leaks * */ res = PQprepare(conn, "qu", "insert into mrow values ($1::bigint, $2::bigint, $3::float);",3, NULL); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "Prepare query failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); const char *paramValues[3]; int paramLengths[3]; int paramFormats[3]; long time = 0, _time = 0; long id = 0, _id = 0; union{ double f; long i; } _value, value; _value.f = 1.0; value.f = 1.0; paramValues[0] = (char*)(&time); paramLengths[0] = sizeof(time); paramFormats[0] = 1; paramValues[1] = (char*)(&id); paramLengths[1] = sizeof(id); paramFormats[1] = 1; paramValues[2] = (char*)(&value); paramLengths[2] = sizeof(value); paramFormats[2] = 1; for(i=0; i < 3; i++){ time = htobe64(_time); id = htobe64(_id); value.i = htobe64(_value.i); _time++; _id++; _value.f += 0.1; res = PQexecPrepared(conn, "qu", 3, paramValues, paramLengths, paramFormats, 1); if (PQresultStatus(res) != PGRES_COMMAND_OK){ fprintf(stderr, "Exec Prepared query failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); } /* end the transaction */ res = PQexec(conn, "END"); PQclear(res); /* close the connection to the database and cleanup */ PQfinish(conn); return 0; }
double CPokerTrackerThread::UpdateStat(int m_chr, int stat) { PGresult *res = NULL; char strQry[k_max_length_of_query] = {0}; char strQry1[k_max_length_of_query] = {0}; char strQry2[k_max_length_of_query] = {0}; const char *n = NULL; double result = -1.0; char siteidstr[k_max_length_of_site_id] = {0}; int siteid = 0; clock_t updStart, updEnd; int duration; int sym_elapsed = p_symbol_engine_time->elapsed(); //No more unnecessary queries when we don't even have a siteid to check siteid = pt_lookup.GetSiteId(); if (siteid == k_undefined) return result; if (!_connected || PQstatus(_pgconn) != CONNECTION_OK) return result; assert(m_chr >= k_min_chair_number); assert(m_chr <= k_max_chair_number); assert(stat >= pt_min); assert(stat <= pt_max); /* TS 01/25/2011. Update means update... we will not back off now :-) */ // If we already have stats cached for the player, the timeout has not expired, // return the value from the cache... //if (sym_elapsed - _player_stats[m_chr].t_elapsed[stat] < prefs.pt_cache_refresh() && //_player_stats[m_chr].t_elapsed[stat] != -1 && //_player_stats[m_chr].stat[stat] != -1) //{ //result = _player_stats[m_chr].stat[stat]; //} // ...otherwise query the database //else { // get query string for the requested statistic strcpy_s(strQry, k_max_length_of_query, query_str3[stat]); // Insert the player name in the query string strcpy_s(strQry1, k_max_length_of_query, strQry); // move the query into temp str 1 while ((n=strstr(strQry1, "%SCREENNAME%"))!=NULL) // find the token in temp str 1 { strcpy_s(strQry2, k_max_length_of_query, strQry1); // move the query into temp str 2 strQry2[n-strQry1]='\0'; // cut off temp str 2 at the beginning of the token strcat_s(strQry2, k_max_length_of_query, _player_stats[m_chr].pt_name); // append the player name to temp str 2 strcat_s(strQry2, k_max_length_of_query, n+12); // append the portion of temp str 1 after the token to temp str 2 strcpy_s(strQry, k_max_length_of_query, strQry2); // move temp str 2 into the original query strcpy_s(strQry1, k_max_length_of_query, strQry); // move the query into temp str 1 } // Insert the site id in the query string sprintf_s(siteidstr, k_max_length_of_site_id, "%d", siteid); strcpy_s(strQry1, k_max_length_of_query, strQry); // move the query into temp str 1 while ((n=strstr(strQry1, "%SITEID%"))!=NULL) // find the token in temp str 1 { strcpy_s(strQry2, k_max_length_of_query, strQry1); // move the query into temp str 2 strQry2[n-strQry1]='\0'; // cut off temp str 2 at the beginning of the token strcat_s(strQry2, k_max_length_of_query, siteidstr); // append the site id to temp str 2 strcat_s(strQry2, k_max_length_of_query, n+8); // append the portion of temp str 1 after the token to temp str 2 strcpy_s(strQry, k_max_length_of_query, strQry2); // move temp str 2 into the original query strcpy_s(strQry1, k_max_length_of_query, strQry); // move the query into temp str 1 } // Do the query against the PT database updStart = clock(); try { // See if we can find the player name in the database write_log_pokertracker(prefs.debug_pokertracker(), "Querying %s for m_chr %d: %s\n", stat_str[stat], m_chr, strQry); res = PQexec(_pgconn, strQry); } catch (_com_error &e) { write_log_pokertracker(prefs.debug_pokertracker(), "ERROR\n"); write_log_pokertracker(prefs.debug_pokertracker(), _T("\tCode = %08lx\n"), e.Error()); write_log_pokertracker(prefs.debug_pokertracker(), _T("\tCode meaning = %s\n"), e.ErrorMessage()); _bstr_t bstrSource(e.Source()); _bstr_t bstrDescription(e.Description()); write_log_pokertracker(prefs.debug_pokertracker(), _T("\tSource = %s\n"), (LPCTSTR) bstrSource); write_log_pokertracker(prefs.debug_pokertracker(), _T("\tDescription = %s\n"), (LPCTSTR) bstrDescription); write_log_pokertracker(prefs.debug_pokertracker(), _T("\tQuery = [%s]\n"), strQry); } updEnd = clock(); duration = (int) ((double)(updEnd - updStart) / 1000); if (duration >= 3) write_log_pokertracker(2, "Query time in seconds: [%d]\n", duration); // Check query return code if (PQresultStatus(res) != PGRES_TUPLES_OK) { switch (PQresultStatus(res)) { case PGRES_COMMAND_OK: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COMMAND_OK: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_EMPTY_QUERY: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_EMPTY_QUERY: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_BAD_RESPONSE: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_BAD_RESPONSE: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_COPY_OUT: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COPY_OUT: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_COPY_IN: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_COPY_IN: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_NONFATAL_ERROR: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_NONFATAL_ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; case PGRES_FATAL_ERROR: write_log_pokertracker(prefs.debug_pokertracker(), "PGRES_FATAL_ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; default: write_log_pokertracker(prefs.debug_pokertracker(), "GENERIC ERROR: %s [%s]\n", PQerrorMessage(_pgconn), strQry); break; } } else { if (PQgetisnull(res,0,0) != 1) { result = atof(PQgetvalue(res,0,0)); write_log_pokertracker(prefs.debug_pokertracker(), "Query %s for m_chr %d success: %f\n", stat_str[stat], m_chr, result); } } PQclear(res); // update cache with new values _player_stats[m_chr].stat[stat] = result; _player_stats[m_chr].t_elapsed[stat] = sym_elapsed; } return result; }
int main(int argc, char **argv) { const char *conninfo; TestSpec *testspec; int i; /* * If the user supplies a parameter on the command line, use it as the * conninfo string; otherwise default to setting dbname=postgres and * using environment variables or defaults for all other connection * parameters. */ if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = postgres"; /* Read the test spec from stdin */ spec_yyparse(); testspec = &parseresult; printf("Parsed test spec with %d sessions\n", testspec->nsessions); /* Establish connections to the database, one for each session */ nconns = testspec->nsessions; conns = calloc(nconns, sizeof(PGconn *)); for (i = 0; i < testspec->nsessions; i++) { PGresult *res; conns[i] = PQconnectdb(conninfo); if (PQstatus(conns[i]) != CONNECTION_OK) { fprintf(stderr, "Connection %d to database failed: %s", i, PQerrorMessage(conns[i])); exit_nicely(); } /* * Suppress NOTIFY messages, which otherwise pop into results at odd * places. */ res = PQexec(conns[i], "SET client_min_messages = warning;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "message level setup failed: %s", PQerrorMessage(conns[i])); exit_nicely(); } PQclear(res); } /* Set the session index fields in steps. */ for (i = 0; i < testspec->nsessions; i++) { Session *session = testspec->sessions[i]; int stepindex; for (stepindex = 0; stepindex < session->nsteps; stepindex++) session->steps[stepindex]->session = i; } /* * Run the permutations specified in the spec, or all if none were * explicitly specified. */ if (testspec->permutations) run_named_permutations(testspec); else run_all_permutations(testspec); /* Clean up and exit */ for (i = 0; i < nconns; i++) PQfinish(conns[i]); return 0; }
bool QgsShapeFile::insertLayer( QString dbname, QString schema, QString primary_key, QString geom_col, QString srid, PGconn * conn, QProgressDialog& pro, bool &fin, QString& errorText ) { Q_UNUSED( dbname ); connect( &pro, SIGNAL( canceled() ), this, SLOT( cancelImport() ) ); import_canceled = false; bool result = true; QString query = QString( "CREATE TABLE %1.%2(%3 SERIAL PRIMARY KEY" ) .arg( QgsPgUtil::quotedIdentifier( schema ) ) .arg( QgsPgUtil::quotedIdentifier( table_name ) ) .arg( QgsPgUtil::quotedIdentifier( primary_key ) ); for ( uint n = 0; n < column_names.size() && result; n++ ) { query += QString( ",%1 %2" ) .arg( QgsPgUtil::quotedIdentifier( column_names[n] ) ) .arg( column_types[n] ); } query += " )"; QgsDebugMsg( "Query string is: " + query ); PGresult *res = PQexec( conn, query.toUtf8() ); if ( PQresultStatus( res ) != PGRES_COMMAND_OK ) { // flag error and send query and error message to stdout on debug errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" ) .arg( query ).arg( PQresultErrorMessage( res ) ); PQclear( res ); return false; } else { PQclear( res ); } query = QString( "SELECT AddGeometryColumn(%1,%2,%3,%4,%5,2)" ) .arg( QgsPgUtil::quotedValue( schema ) ) .arg( QgsPgUtil::quotedValue( table_name ) ) .arg( QgsPgUtil::quotedValue( geom_col ) ) .arg( srid ) .arg( QgsPgUtil::quotedValue( geom_type ) ); res = PQexec( conn, query.toUtf8() ); if ( PQresultStatus( res ) != PGRES_TUPLES_OK ) { errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" ) .arg( query ).arg( PQresultErrorMessage( res ) ); PQclear( res ); return false; } else { PQclear( res ); } if ( isMulti ) { query = QString( "select constraint_name from information_schema.table_constraints where table_schema=%1 and table_name=%2 and constraint_name in ('$2','enforce_geotype_the_geom')" ) .arg( QgsPgUtil::quotedValue( schema ) ) .arg( QgsPgUtil::quotedValue( table_name ) ); QStringList constraints; res = PQexec( conn, query.toUtf8() ); if ( PQresultStatus( res ) == PGRES_TUPLES_OK ) { for ( int i = 0; i < PQntuples( res ); i++ ) constraints.append( PQgetvalue( res, i, 0 ) ); } PQclear( res ); if ( constraints.size() > 0 ) { // drop the check constraint // TODO This whole concept needs to be changed to either // convert the geometries to the same type or allow // multiple types in the check constraint. For now, we // just drop the constraint... query = QString( "alter table %1 drop constraint %2" ) .arg( QgsPgUtil::quotedIdentifier( table_name ) ) .arg( QgsPgUtil::quotedIdentifier( constraints[0] ) ); res = PQexec( conn, query.toUtf8() ); if ( PQresultStatus( res ) != PGRES_COMMAND_OK ) { errorText += tr( "The database gave an error while executing this SQL:\n%1\nThe error was:\n%2\n" ) .arg( query ).arg( PQresultErrorMessage( res ) ); PQclear( res ); return false; } PQclear( res ); } } //adding the data into the table for ( int m = 0; m < features && result; m++ ) { if ( import_canceled ) { fin = true; break; } OGRFeatureH feat = OGR_L_GetNextFeature( ogrLayer ); if ( feat ) { OGRGeometryH geom = OGR_F_GetGeometryRef( feat ); if ( geom ) { query = QString( "INSERT INTO %1.%2(" ) .arg( QgsPgUtil::quotedIdentifier( schema ) ) .arg( QgsPgUtil::quotedIdentifier( table_name ) ); QString values = " VALUES ("; char *geo_temp; // 'GeometryFromText' supports only 2D coordinates // TODO for proper 2.5D support we would need to use 'GeomFromEWkt' if ( hasMoreDimensions ) OGR_G_SetCoordinateDimension( geom, 2 ); OGR_G_ExportToWkt( geom, &geo_temp ); QString geometry( geo_temp ); CPLFree( geo_temp ); for ( uint n = 0; n < column_types.size(); n++ ) { QString val; // FIXME: OGR_F_GetFieldAsString returns junk when called with a 8.255 float field if ( column_types[n] == "float" ) val = qgsDoubleToString( OGR_F_GetFieldAsDouble( feat, n ) ); else val = codec->toUnicode( OGR_F_GetFieldAsString( feat, n ) ); if ( val.isEmpty() ) val = "NULL"; else val = QgsPgUtil::quotedValue( val ); if ( n > 0 ) { query += ","; values += ","; } query += QgsPgUtil::quotedIdentifier( column_names[n] ); values += val; } query += "," + QgsPgUtil::quotedIdentifier( geom_col ); values += QString( ",st_geometryfromtext(%1,%2)" ) .arg( QgsPgUtil::quotedValue( geometry ) ) .arg( srid ); query += ")" + values + ")"; if ( result ) res = PQexec( conn, query.toUtf8() ); if ( PQresultStatus( res ) != PGRES_COMMAND_OK ) { // flag error and send query and error message to stdout on debug result = false; errorText += tr( "The database gave an error while executing this SQL:" ) + "\n"; // the query string can be quite long. Trim if necessary... if ( query.count() > 100 ) errorText += query.left( 150 ) + tr( "... (rest of SQL trimmed)", "is appended to a truncated SQL statement" ) + "\n"; else errorText += query + '\n'; errorText += tr( "The error was:\n%1\n" ).arg( PQresultErrorMessage( res ) ); errorText += '\n'; } else { PQclear( res ); } pro.setValue( pro.value() + 1 ); qApp->processEvents(); } OGR_F_Destroy( feat ); } } // create the GIST index if the load was successful if ( result ) { // prompt user to see if they want to build the index and warn // them about the potential time-cost } OGR_L_ResetReading( ogrLayer ); return result; }
/* * Actual code to make call to the database and print the output data. */ int sql_exec(PGconn *conn, const char *todo, bool quiet) { PGresult *res; int nfields; int nrows; int i, j, l; int *length; char *pad; /* make the call */ res = PQexec(conn, todo); /* check and deal with errors */ if (!res || PQresultStatus(res) > 2) { fprintf(stderr, "oid2name: query failed: %s\n", PQerrorMessage(conn)); fprintf(stderr, "oid2name: query was: %s\n", todo); PQclear(res); PQfinish(conn); exit(-1); } /* get the number of fields */ nrows = PQntuples(res); nfields = PQnfields(res); /* for each field, get the needed width */ length = (int *) pg_malloc(sizeof(int) * nfields); for (j = 0; j < nfields; j++) length[j] = strlen(PQfname(res, j)); for (i = 0; i < nrows; i++) { for (j = 0; j < nfields; j++) { l = strlen(PQgetvalue(res, i, j)); if (l > length[j]) length[j] = strlen(PQgetvalue(res, i, j)); } } /* print a header */ if (!quiet) { for (j = 0, l = 0; j < nfields; j++) { fprintf(stdout, "%*s", length[j] + 2, PQfname(res, j)); l += length[j] + 2; } fprintf(stdout, "\n"); pad = (char *) pg_malloc(l + 1); MemSet(pad, '-', l); pad[l] = '\0'; fprintf(stdout, "%s\n", pad); free(pad); } /* for each row, dump the information */ for (i = 0; i < nrows; i++) { for (j = 0; j < nfields; j++) fprintf(stdout, "%*s", length[j] + 2, PQgetvalue(res, i, j)); fprintf(stdout, "\n"); } /* cleanup */ PQclear(res); free(length); return 0; }
/* * call-seq: * res.result_status() -> Fixnum * * Returns the status of the query. The status value is one of: * * +PGRES_EMPTY_QUERY+ * * +PGRES_COMMAND_OK+ * * +PGRES_TUPLES_OK+ * * +PGRES_COPY_OUT+ * * +PGRES_COPY_IN+ * * +PGRES_BAD_RESPONSE+ * * +PGRES_NONFATAL_ERROR+ * * +PGRES_FATAL_ERROR+ * * +PGRES_COPY_BOTH+ */ static VALUE pgresult_result_status(VALUE self) { return INT2FIX(PQresultStatus(pgresult_get(self))); }
/* * handleCopyOut * receives data as a result of a COPY ... TO STDOUT command * * conn should be a database connection that you just issued COPY TO on * and got back a PGRES_COPY_OUT result. * copystream is the file stream for the data to go to. * * result is true if successful, false if not. */ bool handleCopyOut(PGconn *conn, FILE *copystream) { bool OK = true; char *buf; int ret; PGresult *res; for (;;) { ret = PQgetCopyData(conn, &buf, 0); if (ret < 0) break; /* done or error */ if (buf) { if (fwrite(buf, 1, ret, copystream) != ret) { if (OK) /* complain only once, keep reading data */ psql_error("could not write COPY data: %s\n", strerror(errno)); OK = false; } PQfreemem(buf); } } if (OK && fflush(copystream)) { psql_error("could not write COPY data: %s\n", strerror(errno)); OK = false; } if (ret == -2) { psql_error("COPY data transfer failed: %s", PQerrorMessage(conn)); OK = false; } /* * Check command status and return to normal libpq state. After a * client-side error, the server will remain ready to deliver data. The * cleanest thing is to fully drain and discard that data. If the * client-side error happened early in a large file, this takes a long * time. Instead, take advantage of the fact that PQexec() will silently * end any ongoing PGRES_COPY_OUT state. This does cause us to lose the * results of any commands following the COPY in a single command string. * It also only works for protocol version 3. XXX should we clean up * using the slow way when the connection is using protocol version 2? * * We must not ever return with the status still PGRES_COPY_OUT. Our * caller is unable to distinguish that situation from reaching the next * COPY in a command string that happened to contain two consecutive COPY * TO STDOUT commands. We trust that no condition can make PQexec() fail * indefinitely while retaining status PGRES_COPY_OUT. */ while (res = PQgetResult(conn), PQresultStatus(res) == PGRES_COPY_OUT) { OK = false; PQclear(res); PQexec(conn, "-- clear PGRES_COPY_OUT state"); } if (PQresultStatus(res) != PGRES_COMMAND_OK) { psql_error("%s", PQerrorMessage(conn)); OK = false; } PQclear(res); return OK; }
/* Advance to the next state during an async connection setup * * If the connection is green, this is performed by the regular * sync code so the queries are sent by conn_setup() while in * CONN_STATUS_READY state. */ static int _conn_poll_setup_async(connectionObject *self) { int res = PSYCO_POLL_ERROR; PGresult *pgres; switch (self->status) { case CONN_STATUS_CONNECTING: /* Set the connection to nonblocking now. */ if (pq_set_non_blocking(self, 1) != 0) { break; } self->equote = conn_get_standard_conforming_strings(self->pgconn); self->protocol = conn_get_protocol_version(self->pgconn); self->server_version = conn_get_server_version(self->pgconn); if (3 != self->protocol) { PyErr_SetString(InterfaceError, "only protocol 3 supported"); break; } if (0 > conn_read_encoding(self, self->pgconn)) { break; } self->cancel = conn_get_cancel(self->pgconn); if (self->cancel == NULL) { PyErr_SetString(OperationalError, "can't get cancellation key"); break; } /* asynchronous connections always use isolation level 0, the user is * expected to manage the transactions himself, by sending * (asynchronously) BEGIN and COMMIT statements. */ self->autocommit = 1; /* If the datestyle is ISO or anything else good, * we can skip the CONN_STATUS_DATESTYLE step. */ if (!conn_is_datestyle_ok(self->pgconn)) { Dprintf("conn_poll: status -> CONN_STATUS_DATESTYLE"); self->status = CONN_STATUS_DATESTYLE; if (0 == pq_send_query(self, psyco_datestyle)) { PyErr_SetString(OperationalError, PQerrorMessage(self->pgconn)); break; } Dprintf("conn_poll: async_status -> ASYNC_WRITE"); self->async_status = ASYNC_WRITE; res = PSYCO_POLL_WRITE; } else { Dprintf("conn_poll: status -> CONN_STATUS_READY"); self->status = CONN_STATUS_READY; res = PSYCO_POLL_OK; } break; case CONN_STATUS_DATESTYLE: res = _conn_poll_query(self); if (res == PSYCO_POLL_OK) { res = PSYCO_POLL_ERROR; pgres = pq_get_last_result(self); if (pgres == NULL || PQresultStatus(pgres) != PGRES_COMMAND_OK ) { PyErr_SetString(OperationalError, "can't set datestyle to ISO"); break; } CLEARPGRES(pgres); Dprintf("conn_poll: status -> CONN_STATUS_READY"); self->status = CONN_STATUS_READY; res = PSYCO_POLL_OK; } break; } return res; }