static int pgsql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype) { unsigned char *escaped; pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; size_t tmp_len; switch (paramtype) { case PDO_PARAM_LOB: /* escapedlen returned by PQescapeBytea() accounts for trailing 0 */ escaped = PQescapeByteaConn(H->server, (unsigned char *)unquoted, unquotedlen, &tmp_len); *quotedlen = tmp_len + 1; *quoted = emalloc(*quotedlen + 1); memcpy((*quoted)+1, escaped, *quotedlen-2); (*quoted)[0] = '\''; (*quoted)[*quotedlen-1] = '\''; (*quoted)[*quotedlen] = '\0'; PQfreemem(escaped); break; default: *quoted = safe_emalloc(2, unquotedlen, 3); (*quoted)[0] = '\''; *quotedlen = PQescapeStringConn(H->server, *quoted + 1, unquoted, unquotedlen, NULL); (*quoted)[*quotedlen + 1] = '\''; (*quoted)[*quotedlen + 2] = '\0'; *quotedlen += 2; } return 1; }
/* * Convert a string value to an SQL string literal and append it to * the given buffer. Encoding and string syntax rules are as indicated * by current settings of the PGconn. */ void appendStringLiteralConn(struct pqbuf* buf, const char *str, PGconn *conn) { size_t length = strlen(str); /* * XXX This is a kluge to silence escape_string_warning in our utility * programs. It should go away someday. */ if (strchr(str, '\\') != NULL && PQserverVersion(conn) >= 80100) { /* ensure we are not adjacent to an identifier */ if (buf->len > 0 && buf->data[buf->len - 1] != ' ') append_pqbuf_char(buf, ' '); append_pqbuf_char(buf, ESCAPE_STRING_SYNTAX); appendStringLiteral(buf, str, PQclientEncoding(conn), false); return; } /* XXX end kluge */ if (!enlarge_pqbuf(buf, 2 * length + 2)) return; append_pqbuf_char(buf, '\''); buf->len += PQescapeStringConn(conn, buf->data + buf->len, str, length, NULL); append_pqbuf_char(buf, '\''); }
/* * check_loadable_libraries() * * Check that the new cluster contains all required libraries. * We do this by actually trying to LOAD each one, thereby testing * compatibility as well as presence. */ void check_loadable_libraries(void) { PGconn *conn = connectToServer(&new_cluster, "template1"); int libnum; FILE *script = NULL; bool found = false; char output_path[MAX_PG_PATH]; prep_status("Checking for presence of required libraries"); snprintf(output_path, sizeof(output_path), "%s/loadable_libraries.txt", os_info.cwd); for (libnum = 0; libnum < os_info.num_libraries; libnum++) { char *lib = os_info.libraries[libnum]; int llen = strlen(lib); char *cmd = (char *) pg_malloc(8 + 2 * llen + 1); PGresult *res; strcpy(cmd, "LOAD '"); PQescapeStringConn(conn, cmd + 6, lib, llen, NULL); strcat(cmd, "'"); res = PQexec(conn, cmd); if (PQresultStatus(res) != PGRES_COMMAND_OK) { found = true; if (script == NULL && (script = fopen(output_path, "w")) == NULL) pg_log(PG_FATAL, "Could not create necessary file: %s\n", output_path); fprintf(script, "Failed to load library: %s\n%s\n", lib, PQerrorMessage(conn)); } PQclear(res); pg_free(cmd); } PQfinish(conn); if (found) { fclose(script); pg_log(PG_REPORT, "fatal\n"); pg_log(PG_FATAL, "| Your installation references loadable libraries that are missing\n" "| from the new installation. You can add these libraries to\n" "| the new installation, or remove the functions using them\n" "| from the old installation. A list of the problem libraries\n" "| is in the file\n" "| \"%s\".\n\n", output_path); } else check_ok(); }
/* * do_lo_import() * * Copy large object from file to database */ bool do_lo_import(const char *filename_arg, const char *comment_arg) { PGresult *res; Oid loid; char oidbuf[32]; bool own_transaction; if (!start_lo_xact("\\lo_import", &own_transaction)) return false; SetCancelConn(); loid = lo_import(pset.db, filename_arg); ResetCancelConn(); if (loid == InvalidOid) { psql_error("%s", PQerrorMessage(pset.db)); return fail_lo_xact("\\lo_import", own_transaction); } /* insert description if given */ if (comment_arg) { char *cmdbuf; char *bufptr; size_t slen = strlen(comment_arg); cmdbuf = malloc(slen * 2 + 256); if (!cmdbuf) return fail_lo_xact("\\lo_import", own_transaction); sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid); bufptr = cmdbuf + strlen(cmdbuf); bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL); strcpy(bufptr, "'"); if (!(res = PSQLexec(cmdbuf, false))) { free(cmdbuf); return fail_lo_xact("\\lo_import", own_transaction); } PQclear(res); free(cmdbuf); } if (!finish_lo_xact("\\lo_import", own_transaction)) return false; print_lo_result("lo_import %u", loid); sprintf(oidbuf, "%u", loid); SetVariable(pset.vars, "LASTOID", oidbuf); return true; }
str singlequote(str s) { int err = 0; if (len(s) == 0) return s; str retval = blank(len(s)*2); retval->length = PQescapeStringConn(db->conn,retval->data,s->data,len(s),&err); if (err) dblog("Failed to escape string %s",s); return retval; }
/** * \brief Add a new license to license_ref table * * Adds a license to license_ref table. * * \param char $licenseName * * \return rf_pk for success, 0 for failure */ FUNCTION long add2license_ref(PGconn *pgConn, char *licenseName) { PGresult *result; char query[256]; char insert[256]; char escLicName[256]; char *specialLicenseText; long rf_pk; int len; int error; int numRows; // escape the name len = strlen(licenseName); PQescapeStringConn(pgConn, escLicName, licenseName, len, &error); if (error) printf("WARNING: %s(%d): Does license name have multibyte encoding?", __FILE__, __LINE__); /* verify the license is not already in the table */ sprintf(query, "SELECT rf_pk FROM license_ref where rf_shortname='%s' and rf_detector_type=2", escLicName); result = PQexec(pgConn, query); if (fo_checkPQresult(pgConn, result, query, "add2license_ref", __LINE__)) return 0; numRows = PQntuples(result); if (numRows) { rf_pk = atol(PQgetvalue(result, 0, 0)); return rf_pk; } /* Insert the new license */ specialLicenseText = "License by Nomos."; sprintf( insert, "insert into license_ref(rf_shortname, rf_text, rf_detector_type) values('%s', '%s', 2)", escLicName, specialLicenseText); result = PQexec(pgConn, insert); if (fo_checkPQcommand(pgConn, result, insert, __FILE__, __LINE__)) return 0; PQclear(result); /* retrieve the new rf_pk */ result = PQexec(pgConn, query); if (fo_checkPQresult(pgConn, result, query, "add2license_ref", __LINE__)) return 0; numRows = PQntuples(result); if (numRows) rf_pk = atol(PQgetvalue(result, 0, 0)); else { printf("ERROR: %s:%s:%d Just inserted value is missing. On: %s", __FILE__, "add2license_ref()", __LINE__, query); return(0); } PQclear(result); return (rf_pk); }
// Sets *to to the escaped value void psMysqlConnection::Escape(csString& to, const char *from) { size_t len = strlen(from); char* buff = new char[len*2+1]; if(conn) PQescapeStringConn(conn, buff, from, len, NULL); else PQescapeString(buff, from, len); to = buff; delete[] buff; }
string PostgresDatabase::EscapeString(const char * esc, DatabaseConnection * con) { char a2[16384] = {0}; const char * ret; int err; if(PQescapeStringConn(static_cast<PostgresDatabaseConnection*>(con)->PgSql, a2, (char*)esc, (unsigned long)strlen(esc), &err) == 0) ret = esc; else ret = a2; return string(ret); }
RakNet::RakString PostgreSQLInterface::GetEscapedString(const char *input) const { unsigned long len = (unsigned long) strlen(input); char *fn = (char*) rakMalloc_Ex(len*2+1,_FILE_AND_LINE_); int error; PQescapeStringConn(pgConn, fn, input, len, &error); RakNet::RakString output; // Use assignment so it doesn't parse printf escape strings output = fn; rakFree_Ex(fn,_FILE_AND_LINE_); return output; }
/* ** Escapes a string for use within an SQL statement. ** Returns a string with the escaped string. */ static int conn_escape (lua_State *L) { conn_data *conn = getconnection (L); size_t len; const char *from = luaL_checklstring (L, 2, &len); char to[len*sizeof(char)*2+1]; int error; len = PQescapeStringConn (conn->pg_conn, to, from, len, &error); if (error == 0) { /* success ! */ lua_pushlstring (L, to, len); return 1; } else return luasql_failmsg (L, "cannot escape string. PostgreSQL: ", PQerrorMessage (conn->pg_conn)); }
std::string escape(const std::string &s) { std::string buffer; size_t n=s.size()*2+1; buffer.resize(n); n=PQescapeStringConn(pgconn, &buffer[0], s.c_str(), s.size(), 0); buffer.resize(n); return buffer; }
/* Assume 2 * strlen(from) + 1 buffer in to */ char * SMSDPgSQL_QuoteString(GSM_SMSDConfig * Config, const char *from) { char *to; int ret =0; to = malloc(strlen(from)*2+3); to[0] = '\''; to[1] = '\0'; #ifdef HAVE_PQESCAPESTRINGCONN PQescapeStringConn(Config->conn.pg, to+1, from, strlen(from), &ret); #else PQescapeString(to+1, from, strlen(from)); #endif strcat(to, "'"); return to; }
string PostgresDatabase::EscapeString(string Escape) { char a2[16384] = {0}; DatabaseConnection * con = GetFreeConnection(); const char * ret; int err; if(PQescapeStringConn(static_cast<PostgresDatabaseConnection*>(con)->PgSql, a2, Escape.c_str(), (unsigned long)Escape.length(), &err) == 0) ret = Escape.c_str(); else ret = a2; con->Busy.Release(); return string(ret); }
void PostgresDatabase::EscapeLongString(const char * str, uint32 len, stringstream& out) { char a2[65536*3] = {0}; DatabaseConnection * con = GetFreeConnection(); const char * ret; int err; if(PQescapeStringConn(static_cast<PostgresDatabaseConnection*>(con)->PgSql, a2, str, (unsigned long)len, &err) == 0) ret = str; else ret = a2; out.write(a2, (std::streamsize)strlen(a2)); con->Busy.Release(); }
/* * Use PostgreSQL native handling to escape string * string returned must be freed by the caller * return NULL on error */ char *ows_psql_escape_string(ows *o, const char *content) { char *content_escaped; int error = 0; assert(o); assert(o->pg); assert(content); content_escaped = malloc(strlen(content) * 2 + 1); PQescapeStringConn(o->pg, content_escaped, content, strlen(content), &error); if (error != 0) return NULL; return content_escaped; }
/* * Adapter function to PQescapeStringConn() * This function should properly escape the string argument * appropriately depending on the encoding etc. that is specific to * connection. * Note the single quote is not attached in the return val. */ SEXP RS_PostgreSQL_escape(SEXP conHandle, SEXP preescapestring) { S_EVALUATOR PGconn * my_connection; RS_DBI_connection *con; SEXP output; size_t length; const char *statement_cstr; char *escapedstring; con = RS_DBI_getConnection(conHandle); my_connection = (PGconn *) con->drvConnection; statement_cstr = CHR_EL(preescapestring, 0); length = strlen(statement_cstr); escapedstring = R_alloc(length * 2 + 1, 1); PQescapeStringConn(my_connection, escapedstring, statement_cstr, length, NULL); output = allocVector(STRSXP, 1); SET_STRING_ELT(output, 0, mkChar(escapedstring)); return output; }
std::string DatabasePgSQL::escapeString(const std::string& s) { // remember to quote even empty string! if(!s.size()) return std::string("''"); // the worst case is 2n + 1 int32_t error; char* output = new char[(s.length() * 2) + 1]; // quotes escaped string and frees temporary buffer PQescapeStringConn(m_handle, output, s.c_str(), s.length(), reinterpret_cast<int32_t*>(&error)); std::string r = std::string("'"); r += output; r += "'"; delete[] output; return r; }
void svStorageEnginePostgreSQL::EscapeString(string &value) { #ifdef HAVE_PQESCAPESTRINGCONN if (!value.size()) return; if (!escape_buffer) { escape_buffer_pages = 1; escape_buffer = (char *)realloc(NULL, escape_buffer_pages * page_size); } size_t length = value.size() * 2 + 1; while (length > escape_buffer_pages * page_size) { escape_buffer = (char *)realloc(escape_buffer, ++escape_buffer_pages * page_size); } if (state != svSES_ONLINE || PQstatus(pg_conn) != CONNECTION_OK) Connect(); PQescapeStringConn(pg_conn, escape_buffer, value.c_str(), value.size(), NULL); value = escape_buffer; #endif // HAVE_PQESCAPESTRINGCONN }
VALUE do_postgres_cConnection_quote_string(VALUE self, VALUE string) { PGconn *db = DATA_PTR(rb_iv_get(self, "@connection")); const char *source = rb_str_ptr_readonly(string); int error = 0; long source_len = rb_str_len(string); long buffer_len = source_len * 2 + 3; // Overflow check if(buffer_len <= source_len) { rb_raise(rb_eArgError, "Input string is too large to be safely quoted"); } char *escaped; // Allocate space for the escaped version of 'string' // http://www.postgresql.org/docs/8.3/static/libpq-exec.html#LIBPQ-EXEC-ESCAPE-STRING if (!(escaped = calloc(buffer_len, sizeof(char)))) { rb_memerror(); } long quoted_length; VALUE result; // Escape 'source' using the current charset in use on the conection 'db' quoted_length = PQescapeStringConn(db, escaped + 1, source, source_len, &error); if(error) { rb_raise(eDO_DataError, "%s", PQerrorMessage(db)); } // Wrap the escaped string in single-quotes, this is DO's convention escaped[0] = escaped[quoted_length + 1] = '\''; result = DATA_OBJECTS_STR_NEW(escaped, quoted_length + 2, FIX2INT(rb_iv_get(self, "@encoding_id")), NULL); free(escaped); return result; }
CAMLprim value PQescapeStringConn_stub( value v_conn, value v_from, value v_pos_from, value v_len) { size_t len = Long_val(v_len); size_t to_len = len + len + 1; char *buf = malloc(to_len); int error; size_t n_written = PQescapeStringConn( get_conn(v_conn), buf, String_val(v_from) + Long_val(v_pos_from), len, &error); if (error) { free(buf); caml_failwith("Postgresql.escape_string_conn: failed to escape string"); return Val_unit; } else { value v_res = caml_alloc_string(n_written); memcpy(String_val(v_res), buf, n_written); free(buf); return v_res; } }
void db_logMessage(DB *d, int tasknum, int type, char *msg) { char querystr[] = "INSERT INTO messages ( jobid, msg_type, tasknum, msg ) VALUES ( %d, %d, %d, '%s' );"; size_t limit = strlen(msg)*2; char *es_msg = (char*) malloc(sizeof(char) * limit); limit = PQescapeStringConn(d->conn, es_msg, msg, strlen(msg), NULL); //Returns bytes written to es_msg limit = sizeof(querystr) + 3*sizeof(int) + limit; //Set size of insert char *qry = (char*) malloc(sizeof(char) * limit + 1); snprintf(qry, limit, querystr, d->jobid, type, tasknum, es_msg); d->res = PQexec(d->conn, qry); if ( PQresultStatus(d->res) != PGRES_COMMAND_OK ) { fprintf(stderr, "Error ending job, setting time: %s", PQerrorMessage(d->conn)); PQclear(d->res); db_closeConnection(d); exit(1); } PQclear(d->res); free(qry); free(es_msg); }
/* utility function to safely escape table names */ char *escape_string(PGconn *pgsql, const char *input) { /* length of string */ size_t input_len = strlen(input); char *scratch; size_t scratch_len; char *output; /* worst case is every char escaped plus terminating NUL */ scratch = malloc(input_len*2+1); /* escape the string */ scratch_len = PQescapeStringConn(pgsql, scratch, input, input_len, NULL); if (scratch_len) { output = strndup(scratch, scratch_len); free(scratch); } else { output = NULL; } db_debug(DEBUG, "escape_string input = '%s' output = '%s'\n", input, output); return output; }
void submit(SQLQuery *req, const std::string& q, const ParamL& p) { std::string res; unsigned int param = 0; for(std::string::size_type i = 0; i < q.length(); i++) { if (q[i] != '?') res.push_back(q[i]); else { if (param < p.size()) { std::string parm = p[param++]; std::vector<char> buffer(parm.length() * 2 + 1); int error; size_t escapedsize = PQescapeStringConn(sql, &buffer[0], parm.data(), parm.length(), &error); if (error) ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "BUG: Apparently PQescapeStringConn() failed"); res.append(&buffer[0], escapedsize); } } } submit(req, res); }
CPLString OGRPGDumpEscapeString( const char* pszStrValue, int nMaxLength, const char* pszFieldName) { CPLString osCommand; /* We need to quote and escape string fields. */ osCommand += "'"; int nSrcLen = strlen(pszStrValue); int nSrcLenUTF = CPLStrlenUTF8(pszStrValue); if (nMaxLength > 0 && nSrcLenUTF > nMaxLength) { CPLDebug( "PG", "Truncated %s field value, it was too long.", pszFieldName ); int iUTF8Char = 0; for(int iChar = 0; iChar < nSrcLen; iChar++ ) { if( (((unsigned char *) pszStrValue)[iChar] & 0xc0) != 0x80 ) { if( iUTF8Char == nMaxLength ) { nSrcLen = iChar; break; } iUTF8Char ++; } } } char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1); /* -------------------------------------------------------------------- */ /* PQescapeStringConn was introduced in PostgreSQL security releases */ /* 8.1.4, 8.0.8, 7.4.13, 7.3.15 */ /* PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure' */ /* so it is not set by default when building OGR for Win32 */ /* -------------------------------------------------------------------- */ #if defined(PG_HAS_PQESCAPESTRINGCONN) int nError; PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError); if (nError == 0) osCommand += pszDestStr; else CPLError(CE_Warning, CPLE_AppDefined, "PQescapeString(): %s\n" " input: '%s'\n" " got: '%s'\n", PQerrorMessage( hPGConn ), pszStrValue, pszDestStr ); #else //PQescapeString(pszDestStr, pszStrValue, nSrcLen); int i, j; for(i=0,j=0; i < nSrcLen; i++) { if (pszStrValue[i] == '\'') { pszDestStr[j++] = '\''; pszDestStr[j++] = '\''; } /* FIXME: at some point (when we drop PostgreSQL < 9.1 support, remove the escaping of backslash and remove 'SET standard_conforming_strings = OFF' in CreateLayer() */ else if (pszStrValue[i] == '\\') { pszDestStr[j++] = '\\'; pszDestStr[j++] = '\\'; } else pszDestStr[j++] = pszStrValue[i]; } pszDestStr[j] = 0; osCommand += pszDestStr; #endif CPLFree(pszDestStr); osCommand += "'"; return osCommand; }
static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; int num_rows = 0, pgerror; char sql[256], escapebuf[513]; char *stringp; char *chunk; char *op; const char *newparam, *newval; struct ast_variable *var = NULL, *prev = NULL; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return NULL; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return NULL; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ op = strchr(newparam, ' ') ? "" : " ="; PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) op = " ="; else op = ""; PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, escapebuf); } va_end(ap); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return NULL; } if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return NULL; } } ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); if ((num_rows = PQntuples(result)) > 0) { int i = 0; int rowIndex = 0; int numFields = PQnfields(result); char **fieldnames = NULL; ast_debug(1, "PostgreSQL RealTime: Found %d rows.\n", num_rows); if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { ast_mutex_unlock(&pgsql_lock); PQclear(result); return NULL; } for (i = 0; i < numFields; i++) fieldnames[i] = PQfname(result, i); for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { for (i = 0; i < numFields; i++) { stringp = PQgetvalue(result, rowIndex, i); while (stringp) { chunk = strsep(&stringp, ";"); if (!ast_strlen_zero(ast_strip(chunk))) { if (prev) { prev->next = ast_variable_new(fieldnames[i], chunk, ""); if (prev->next) { prev = prev->next; } } else { prev = var = ast_variable_new(fieldnames[i], chunk, ""); } } } } } ast_free(fieldnames); } else { ast_debug(1, "Postgresql RealTime: Could not find any rows in table %s.\n", table); } ast_mutex_unlock(&pgsql_lock); PQclear(result); return var; }
static int destroy_pgsql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) { PGresult *result = NULL; int numrows = 0; int pgresult; char sql[256]; char buf[256], buf2[256]; const char *newparam, *newval; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return -1; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ /*newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) {*/ if (ast_strlen_zero(keyfield) || ast_strlen_zero(lookup)) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime destroy requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return -1; } /* Must connect to the server before anything else, as the escape function requires the connection handle.. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return -1; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ PQescapeStringConn(pgsqlConn, buf, keyfield, sizeof(keyfield), &pgresult); PQescapeStringConn(pgsqlConn, buf2, lookup, sizeof(lookup), &pgresult); snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE %s = '%s'", table, buf, buf2); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); PQescapeStringConn(pgsqlConn, buf, newparam, sizeof(newparam), &pgresult); PQescapeStringConn(pgsqlConn, buf2, newval, sizeof(newval), &pgresult); snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s = '%s'", buf, buf2); } va_end(ap); ast_debug(1, "PostgreSQL RealTime: Delete SQL: %s\n", sql); if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return -1; } } numrows = atoi(PQcmdTuples(result)); ast_mutex_unlock(&pgsql_lock); ast_debug(1, "PostgreSQL RealTime: Deleted %d rows on table: %s\n", numrows, table); /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html * An integer greater than zero indicates the number of rows affected * Zero indicates that no records were updated * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) */ if (numrows >= 0) return (int) numrows; return -1; }
static int store_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; Oid insertid; char sql[256]; char params[256]; char vals[256]; char buf[256]; int pgresult; const char *newparam, *newval; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return -1; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime storage requires at least 1 parameter and 1 value to store.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return -1; } /* Must connect to the server before anything else, as the escape function requires the connection handle.. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return -1; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ PQescapeStringConn(pgsqlConn, buf, newparam, sizeof(newparam), &pgresult); snprintf(params, sizeof(params), "%s", buf); PQescapeStringConn(pgsqlConn, buf, newval, sizeof(newval), &pgresult); snprintf(vals, sizeof(vals), "'%s'", buf); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); PQescapeStringConn(pgsqlConn, buf, newparam, sizeof(newparam), &pgresult); snprintf(params + strlen(params), sizeof(params) - strlen(params), ", %s", buf); PQescapeStringConn(pgsqlConn, buf, newval, sizeof(newval), &pgresult); snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", '%s'", buf); } va_end(ap); snprintf(sql, sizeof(sql), "INSERT INTO (%s) VALUES (%s)", params, vals); ast_debug(1, "PostgreSQL RealTime: Insert SQL: %s\n", sql); if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return -1; } } insertid = PQoidValue(result); ast_mutex_unlock(&pgsql_lock); ast_debug(1, "PostgreSQL RealTime: row inserted on table: %s, id: %u\n", table, insertid); /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html * An integer greater than zero indicates the number of rows affected * Zero indicates that no records were updated * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) */ if (insertid >= 0) return (int) insertid; return -1; }
/* * Used when converting result from a query */ int db_postgres_val2str(const db_con_t* _con, const db_val_t* _v, char* _s, int* _len) { int l, ret; int pgret; char *tmp_s; size_t tmp_len; char* old_s; if ((!_v) || (!_s) || (!_len) || (!*_len)) { LM_ERR("invalid parameter value\n"); return -1; } if (VAL_NULL(_v)) { if ( *_len < (l=(int)sizeof("NULL")-1)) { LM_ERR("buffer too short to print NULL\n"); return -1; } memcpy(_s, "NULL", l); *_len = l; return 0; } switch(VAL_TYPE(_v)) { case DB_INT: if (db_int2str(VAL_INT(_v), _s, _len) < 0) { LM_ERR("failed to convert string to int\n"); return -2; } else { return 0; } break; case DB_BIGINT: if (db_bigint2str(VAL_BIGINT(_v), _s, _len) < 0) { LM_ERR("failed to convert string to big int\n"); return -2; } else { return 0; } break; case DB_BITMAP: if (db_int2str(VAL_BITMAP(_v), _s, _len) < 0) { LM_ERR("failed to convert string to int\n"); return -3; } else { return 0; } break; case DB_DOUBLE: if (db_double2str(VAL_DOUBLE(_v), _s, _len) < 0) { LM_ERR("failed to convert string to double\n"); return -3; } else { return 0; } break; case DB_STRING: l = strlen(VAL_STRING(_v)); if (*_len < (l * 2 + 3)) { LM_ERR("destination STRING buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -4; } else { old_s = _s; *_s++ = '\''; ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v), l, &pgret); if(pgret!=0) { LM_ERR("PQescapeStringConn failed\n"); return -4; } LM_DBG("PQescapeStringConn: in: %d chars," " out: %d chars\n", l, ret); _s += ret; *_s++ = '\''; *_s = '\0'; /* FIXME */ *_len = _s - old_s; return 0; } break; case DB_STR: l = VAL_STR(_v).len; if (*_len < (l * 2 + 3)) { LM_ERR("destination STR buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -5; } else { old_s = _s; *_s++ = '\''; ret = PQescapeStringConn(CON_CONNECTION(_con), _s, VAL_STRING(_v), l, &pgret); if(pgret!=0) { LM_ERR("PQescapeStringConn failed \n"); return -5; } LM_DBG("PQescapeStringConn: in: %d chars, out: %d chars\n", l, ret); _s += ret; *_s++ = '\''; *_s = '\0'; /* FIXME */ *_len = _s - old_s; return 0; } break; case DB_DATETIME: if (db_time2str(VAL_TIME(_v), _s, _len) < 0) { LM_ERR("failed to convert string to time_t\n"); return -6; } else { return 0; } break; case DB_BLOB: l = VAL_BLOB(_v).len; /* this estimation is not always correct, thus we need to check later again */ if (*_len < (l * 2 + 3)) { LM_ERR("destination BLOB buffer too short (have %d, need %d)\n", *_len, l * 2 + 3); return -7; } else { *_s++ = '\''; tmp_s = (char*)PQescapeByteaConn(CON_CONNECTION(_con), (unsigned char*)VAL_STRING(_v), (size_t)l, (size_t*)&tmp_len); if(tmp_s==NULL) { LM_ERR("PQescapeBytea failed\n"); return -7; } if (tmp_len > *_len) { LM_ERR("escaped result too long\n"); return -7; } memcpy(_s, tmp_s, tmp_len); PQfreemem(tmp_s); tmp_len = strlen(_s); *(_s + tmp_len) = '\''; *(_s + tmp_len + 1) = '\0'; *_len = tmp_len + 2; return 0; } break; default: LM_DBG("unknown data type\n"); return -7; } }
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(); if (!conn) /* Error message already written in GetConnection() */ exit(1); /* * 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 send replication command \"%s\": %s"), progname, "IDENTIFY_SYSTEM", PQerrorMessage(conn)); disconnect_and_exit(1); } if (PQntuples(res) != 1 || PQnfields(res) != 3) { fprintf(stderr, _("%s: could not identify system: got %d rows and %d fields, expected %d rows and %d fields\n"), progname, PQntuples(res), PQnfields(res), 1, 3); disconnect_and_exit(1); } sysidentifier = pg_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 replication command \"%s\": %s"), progname, "BASE_BACKUP", 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, "transaction log 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 transaction log end position from server: %s"), progname, PQerrorMessage(conn)); disconnect_and_exit(1); } if (PQntuples(res) != 1) { fprintf(stderr, _("%s: no transaction log end position returned from server\n"), progname); disconnect_and_exit(1); } strcpy(xlogend, PQgetvalue(res, 0, 0)); if (verbose && includewal) fprintf(stderr, "transaction log 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; uint32 hi, lo; #endif if (verbose) fprintf(stderr, _("%s: waiting for background process to finish streaming...\n"), progname); #ifndef WIN32 if (write(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 %d died, expected %d\n"), progname, r, (int) 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 %d\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", &hi, &lo) != 2) { fprintf(stderr, _("%s: could not parse transaction log location \"%s\"\n"), progname, xlogend); disconnect_and_exit(1); } xlogendptr = ((uint64) hi) << 32 | lo; 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); }
static int update_pgsql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) { PGresult *result = NULL; int numrows = 0, pgerror; char sql[256], escapebuf[513]; const char *newparam, *newval; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return -1; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return -1; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return -1; } snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, escapebuf); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return -1; } snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, escapebuf); } va_end(ap); PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup); va_end(ap); return -1; } snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, escapebuf); ast_debug(1, "PostgreSQL RealTime: Update SQL: %s\n", sql); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return -1; } if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return -1; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return -1; } } numrows = atoi(PQcmdTuples(result)); ast_mutex_unlock(&pgsql_lock); ast_debug(1, "PostgreSQL RealTime: Updated %d rows on table: %s\n", numrows, table); /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html * An integer greater than zero indicates the number of rows affected * Zero indicates that no records were updated * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) */ if (numrows >= 0) return (int) numrows; return -1; }