/* * Adapter function to PQunescapeBytea() * This function should properly unescape the charactor representation * of the binary data returned from PostgreSQL and return raw binary data. */ SEXP RS_PostgreSQL_unescape_bytea(SEXP escapedstring) { SEXP output; size_t raw_length; const char* strbuffer; unsigned char* rawbuffer; strbuffer = CHAR(STRING_ELT(escapedstring, 0)); if(!strbuffer) RS_DBI_errorMessage("strbuffer is NULL!", RS_DBI_ERROR); if (strbuffer[0] == '\\' && strbuffer[1] == 'x'){ /* the new hex fomat */ int i; size_t enc_length = LENGTH(STRING_ELT(escapedstring, 0)); raw_length = enc_length / 2 - 1; output = allocVector(RAWSXP, raw_length); rawbuffer = RAW(output); for(i = 0; i < raw_length; i++){ rawbuffer[i] = (hex2n(strbuffer[2+ i*2]) << 4) + hex2n(strbuffer[2+i*2+1]); } return output; }else{ /* the old escape format */ rawbuffer = PQunescapeBytea((const unsigned char*) strbuffer, &raw_length); /* explicit cast to suppress warning on signedness by clang */ if(!rawbuffer) RS_DBI_errorMessage("PQunescapeByea Failed", RS_DBI_ERROR); output = allocVector(RAWSXP, raw_length); memcpy(RAW(output), rawbuffer, raw_length); free(rawbuffer); return output; } }
VALUE typecast_detect(const char *data, size_t size, int type) { VALUE value; char *bytea; size_t bytea_len; switch (type) { case SWIFT_TYPE_INT: return rb_cstr2inum(data, 10); case SWIFT_TYPE_FLOAT: return rb_float_new(atof(data)); case SWIFT_TYPE_NUMERIC: return rb_funcall(cBigDecimal, fnew, 1, rb_str_new(data, size)); case SWIFT_TYPE_BOOLEAN: return (data && (data[0] =='t' || data[0] == '1')) ? Qtrue : Qfalse; case SWIFT_TYPE_BLOB: bytea = PQunescapeBytea(data, &bytea_len); value = rb_str_new(bytea, bytea_len); PQfreemem(bytea); return rb_funcall(cStringIO, fnew, 1, value); case SWIFT_TYPE_TIMESTAMP: return datetime_parse(cSwiftDateTime, data, size); case SWIFT_TYPE_DATE: return date_parse(cSwiftDateTime, data, size); default: return rb_enc_str_new(data, size, rb_utf8_encoding()); } }
static VALUE typecast(const char *value, long length, const VALUE type, int encoding) { if (type == rb_cInteger) { return rb_cstr2inum(value, 10); } else if (type == rb_cString) { return DO_STR_NEW(value, length, encoding); } else if (type == rb_cFloat) { return rb_float_new(rb_cstr_to_dbl(value, Qfalse)); } else if (type == rb_cBigDecimal) { return rb_funcall(rb_cBigDecimal, ID_NEW, 1, rb_str_new(value, length)); } else if (type == rb_cDate) { return parse_date(value); } else if (type == rb_cDateTime) { return parse_date_time(value); } else if (type == rb_cTime) { return parse_time(value); } else if (type == rb_cTrueClass) { return *value == 't' ? Qtrue : Qfalse; } else if (type == rb_cByteArray) { size_t new_length = 0; char* unescaped = (char *)PQunescapeBytea((unsigned char*)value, &new_length); VALUE byte_array = rb_funcall(rb_cByteArray, ID_NEW, 1, rb_str_new(unescaped, new_length)); PQfreemem(unescaped); return byte_array; } else if (type == rb_cClass) { return rb_funcall(rb_cObject, rb_intern("full_const_get"), 1, rb_str_new(value, length)); } else if (type == rb_cObject) { return rb_marshal_load(rb_str_new(value, length)); } else if (type == rb_cNilClass) { return Qnil; } else { return DO_STR_NEW(value, length, encoding); } }
static VALUE typecast(const char* data, uint64_t len, int pgtype) { size_t bytea_len; unsigned char* bytea; VALUE rv; switch(pgtype) { case 16: return *data == 't' ? Qtrue : Qfalse; case 17: bytea = PQunescapeBytea(data, &bytea_len); rv = rb_funcall(cStringIO, fnew, 1, rb_str_new(bytea, bytea_len)); PQfreemem(bytea); return rv; case 20: case 21: case 22: case 23: case 26: return rb_cstr2inum(data, 10); case 700: case 701: case 790: return rb_float_new(atof(data)); case 1700: return rb_funcall(cBigDecimal, fnew, 1, rb_str_new(data, len)); case 1082: return typecast_date(data, len); case 1114: case 1184: return typecast_timestamp(data, len); default: return rb_str_new(data, len); } }
/* -------------------------------- * ForwardCacheToFrontend - simply forwards cached data to the frontend * * since the cached data passed from the caller is in escaped binary string * format, unescape it and send it to the frontend appending 'Z' at the end. * returns 0 on success, -1 otherwise. * -------------------------------- */ static int ForwardCacheToFrontend(POOL_CONNECTION *frontend, char *cache, char tstate) { int sendlen; size_t sz; char *binary_cache = NULL; binary_cache = (char *)PQunescapeBytea((unsigned char *)cache, &sz); sendlen = (int) sz; if (malloc_failed(binary_cache)) return -1; pool_debug("ForwardCacheToFrontend: query cache found (%d bytes)", sendlen); /* forward cache to the frontend */ pool_write(frontend, binary_cache, sendlen); /* send ReadyForQuery to the frontend*/ pool_write(frontend, "Z", 1); sendlen = htonl(5); pool_write(frontend, &sendlen, sizeof(int)); if (pool_write_and_flush(frontend, &tstate, 1) < 0) { pool_error("pool_query_cache_lookup: error while writing data to the frontend"); PQfreemem(binary_cache); return -1; } PQfreemem(binary_cache); return 0; }
static inline QByteArray byteArrayFromData(const char *data) { size_t unescapedLen; unsigned char *unescapedData = PQunescapeBytea((const unsigned char*)data, &unescapedLen); const QByteArray result((const char*)unescapedData, unescapedLen); //! @todo avoid deep copy; QByteArray does not allow passing ownership of data; maybe copy PQunescapeBytea code? PQfreemem(unescapedData); return result; }
void pp_export(PGconn * conn, const char * query) { const int ascFmt = 0; int len = 0, i; int rows, ncol, icol; char * val; char * file; PGresult * res; const char * const * ival = (const char * const *) &val; FILE * fimg; /* execute the user provided query */ res = PQexecParams(conn, query, 0, //n. of params NULL, //oids guessed by backend NULL, NULL, NULL, ascFmt); if (PQresultStatus(res) != PGRES_TUPLES_OK) { pp_print_error(PQerrorMessage(conn)); PQclear(res); return; } /* some check */ icol = PQfnumber(res, opts.imagecol); if(icol==-1) { fprintf(stderr, "ERROR: Image column '%s' does not exist in result set.\n", opts.imagecol); PQclear(res); return; } if (!opts.nameprefix) { ncol = PQfnumber(res, opts.namecol); if(ncol==-1) { fprintf(stderr, "ERROR: Name column '%s' does not exist in result set.\n", opts.namecol); PQclear(res); return; } } rows = PQntuples(res); /* fetch the data and save */ for (i = 0; i < rows; ++i) { val = PQunescapeBytea( PQgetvalue(res, i, icol), &len); if(opts.namecol) file = PQgetvalue(res, i, ncol); else file = image_name(opts.nameprefix, i); fimg = fopen(file, "w"); fwrite(val, len, 1, fimg); fclose(fimg); PQfreemem(val); fprintf(stderr, "INFO: exported file %s\n", file); } PQclear(res); }
const char* PgSQLResult::getDataStream(const std::string& s, uint64_t& size) { std::string buf = PQgetvalue(m_handle, m_cursor, PQfnumber(m_handle, s.c_str())); uint8_t* temp = PQunescapeBytea( (const uint8_t*)buf.c_str(), (size_t*)&size); char* value = new char[buf.size()]; strcpy(value, (char*)temp); PQfreemem(temp); return value; }
/* * Document-class: PG::TextDecoder::Bytea < PG::SimpleDecoder * * This is a decoder class for conversion of PostgreSQL bytea type * to binary String objects. * */ static VALUE pg_text_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx) { struct pg_blob_initialization bi; bi.blob_string = (char *)PQunescapeBytea((unsigned char*)val, &bi.length); if (bi.blob_string == NULL) { rb_raise(rb_eNoMemError, "PQunescapeBytea failure: probably not enough memory"); } return rb_ensure(pg_create_blob, (VALUE)&bi, pg_pq_freemem, (VALUE)bi.blob_string); }
CL_DataBuffer CL_PgsqlReaderProvider::get_column_binary(int index) const { const unsigned char *const str = reinterpret_cast<unsigned char*>(PQgetvalue(result, current_row, index)); if (str == nullptr) throw ("Index out of range"); size_t length; auto deleter = [](void *ptr) {if (ptr) {free(ptr);} }; CL_UniquePtr<unsigned char, decltype(deleter)> value(PQunescapeBytea( str, &length), deleter); CL_DataBuffer output(value.get(), length); return output; }
/* * Document-class: PG::TextDecoder::Bytea < PG::SimpleDecoder * * This is a decoder class for conversion of PostgreSQL bytea type * to binary String objects. * */ static VALUE pg_text_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx) { unsigned char *to; size_t to_len; VALUE ret; to = PQunescapeBytea( (unsigned char *)val, &to_len); ret = rb_tainted_str_new((char*)to, to_len); PQfreemem(to); return ret; }
static inline value unescape_bytea(const char *s) { size_t len; value v_res; char *buf = (char *) PQunescapeBytea((unsigned char*) s, &len); if (buf == NULL) { caml_failwith("Postgresql.unescape_bytea: illegal bytea string"); return Val_unit; } v_res = caml_alloc_string(len); memcpy(String_val(v_res), buf, len); PQfreemem(buf); return v_res; }
VALUE do_postgres_typecast(const char *value, long length, const VALUE type, int encoding) { if (type == rb_cTrueClass) { return *value == 't' ? Qtrue : Qfalse; } else if (type == rb_cByteArray) { size_t new_length = 0; char *unescaped = (char *)PQunescapeBytea((unsigned char*)value, &new_length); VALUE byte_array = rb_funcall(rb_cByteArray, DO_ID_NEW, 1, rb_str_new(unescaped, new_length)); PQfreemem(unescaped); return byte_array; } else { return data_objects_typecast(value, length, type, encoding); } }
void operator()(std::ostream* v) { if(blob_ == bytea_type) { unsigned char *val = (unsigned char*)PQgetvalue(res_, current_, fetch_col_); size_t len = 0; unsigned char *buf = PQunescapeBytea(val, &len); if(!buf) throw bad_value_cast(); BOOST_SCOPE_EXIT((buf)) { PQfreemem(buf); } BOOST_SCOPE_EXIT_END v->write((char *)buf,len); }
BYTE * CPgSQL::ReadScorcoData(const char * SQL, const char * param, BOOL * pSqlError, int * size) { *pSqlError = false; *size = 0; PGresult* rco_result = NULL; if ( strcmp(param, "FETCHMODE") != 0 ) { // In normal mode (NOT in FETCHMODE), run the SQL query for a new result set rco_result = PQexec(pgsql, SQL); } else { // In FETCHMODE, use the result set from previous call to EXEC of a SQL query. rco_result = result; } if ( PQresultStatus(rco_result) != PGRES_TUPLES_OK ) { PQclear(rco_result); *pSqlError = true; return NULL; } if ( PQntuples(rco_result) > 0 ) { // At lest one row left in the result set, assume it's the first field from the query, // unescape it (since PostgreSQL is being queried in text mode), and return it in a // heap allocated block of memory for the NWN VM to deallocate. unsigned int one_field_len = PQgetlength(rco_result, 0, 0); unsigned char* one_field = (unsigned char*)PQgetvalue(rco_result, 0, 0); // static do not deallocate ! unsigned int unesc_field_len = 0; unsigned char *unesc_field = PQunescapeBytea(one_field, &unesc_field_len); if (unesc_field == NULL) { *pSqlError = true; return NULL; } PQclear(rco_result); *size = unesc_field_len; return unesc_field; } else { PQclear (rco_result); return NULL; } return NULL; }
/*! * \brief Convert a str to a db value, copy strings * * Convert a str to a db value, copy strings. * The postgresql module uses a custom escape function for BLOBs. * If the _s is linked in the db_val result, it will be returned zero * \param _t destination value type * \param _v destination value * \param _s source string * \param _l string length * \return 0 on success, negative on error */ int db_postgres_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l) { /* use common function for non BLOB, NULL setting and input * parameter checking */ if ( _t != DB1_BLOB || _s == NULL || _v == NULL) { return db_str2val(_t, _v, _s, _l, 1); } else { char * tmp_s = NULL; LM_DBG("converting BLOB [%.*s]\n", _l, _s); /* * The string is stored in new allocated memory, which we could * not free later thus we need to copy it to some new memory here. */ tmp_s = (char*)PQunescapeBytea((unsigned char*)_s, (size_t*)(void*)&(VAL_BLOB(_v).len)); if(tmp_s==NULL) { LM_ERR("PQunescapeBytea failed\n"); return -7; } VAL_BLOB(_v).s = pkg_malloc(VAL_BLOB(_v).len + 1); if (VAL_BLOB(_v).s == NULL) { LM_ERR("no private memory left\n"); PQfreemem(tmp_s); return -8; } LM_DBG("allocate %d+1 bytes memory for BLOB at %p", VAL_BLOB(_v).len, VAL_BLOB(_v).s); memcpy(VAL_BLOB(_v).s, tmp_s, VAL_BLOB(_v).len); PQfreemem(tmp_s); VAL_BLOB(_v).s[VAL_BLOB(_v).len] = '\0'; VAL_TYPE(_v) = DB1_BLOB; VAL_FREE(_v) = 1; LM_DBG("got blob len %d\n", _l); return 0; } }
/* * Convert a str to a db value, does not copy strings * The postgresql module uses a custom escape function for BLOBs, * so the common db_str2val function from db_ut.h could not used. * If the _s is linked in the db_val result, it will be returned zero */ int pg_str2val(db_type_t _t, db_val_t* _v, char* _s, int _l) { static str dummy_string = {"", 0}; #ifdef PARANOID if (!_v) { LM_ERR("db_val_t parameter cannot be NULL\n"); } #endif if (!_s) { memset(_v, 0, sizeof(db_val_t)); /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STRING(_v) = dummy_string.s; VAL_STR(_v) = dummy_string; VAL_BLOB(_v) = dummy_string; VAL_TYPE(_v) = _t; VAL_NULL(_v) = 1; return 0; } VAL_NULL(_v) = 0; switch(_t) { case DB_INT: LM_DBG("converting INT [%s]\n", _s); if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("failed to convert INT value from string\n"); return -2; } else { VAL_TYPE(_v) = DB_INT; return 0; } break; case DB_BITMAP: LM_DBG("converting BITMAP [%s]\n", _s); if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("failed to convert BITMAP value from string\n"); return -3; } else { VAL_TYPE(_v) = DB_BITMAP; return 0; } break; case DB_DOUBLE: LM_DBG("converting DOUBLE [%s]\n", _s); if (db_str2double(_s, &VAL_DOUBLE(_v)) < 0) { LM_ERR("failed to convert DOUBLE value from string\n"); return -4; } else { VAL_TYPE(_v) = DB_DOUBLE; return 0; } break; case DB_STRING: LM_DBG("converting STRING [%s]\n", _s); VAL_STRING(_v) = _s; VAL_TYPE(_v) = DB_STRING; return 0; case DB_STR: LM_DBG("converting STR [%s]\n", _s); VAL_STR(_v).s = (char*)_s; VAL_STR(_v).len = _l; VAL_TYPE(_v) = DB_STR; _s = 0; return 0; case DB_DATETIME: LM_DBG("converting DATETIME [%s]\n", _s); if (db_str2time(_s, &VAL_TIME(_v)) < 0) { LM_ERR("failed to convert datetime\n"); return -5; } else { VAL_TYPE(_v) = DB_DATETIME; return 0; } break; case DB_BLOB: LM_DBG("converting BLOB [%s]\n", _s); /* PQunescapeBytea: Converts a string representation of binary data * into binary data — the reverse of PQescapeBytea. * This is needed when retrieving bytea data in text format, * but not when retrieving it in binary format. */ VAL_BLOB(_v).s = (char*)PQunescapeBytea((unsigned char*)_s, (size_t*)(void*)&(VAL_BLOB(_v).len) ); VAL_TYPE(_v) = DB_BLOB; LM_DBG("got blob len %d\n", _l); return 0; } return -6; }
QVariant QPSQLResult::data(int i) { if (i >= PQnfields(d->result)) { qWarning("QPSQLResult::data: column %d out of range", i); return QVariant(); } int ptype = PQftype(d->result, i); QVariant::Type type = qDecodePSQLType(ptype); const char *val = PQgetvalue(d->result, at(), i); if (PQgetisnull(d->result, at(), i)) return QVariant(type); switch (type) { case QVariant::Bool: return QVariant((bool)(val[0] == 't')); case QVariant::String: return d->driver->isUtf8 ? QString::fromUtf8(val) : QString::fromAscii(val); case QVariant::LongLong: if (val[0] == '-') return QString::fromLatin1(val).toLongLong(); else return QString::fromLatin1(val).toULongLong(); case QVariant::Int: return atoi(val); case QVariant::Double: if (ptype == QNUMERICOID) { if (d->precisionPolicy != QSql::HighPrecision) { QVariant retval; bool convert; if (d->precisionPolicy == QSql::LowPrecisionInt64) retval = QString::fromAscii(val).toLongLong(&convert); else if (d->precisionPolicy == QSql::LowPrecisionInt32) retval = QString::fromAscii(val).toInt(&convert); else if (d->precisionPolicy == QSql::LowPrecisionDouble) retval = QString::fromAscii(val).toDouble(&convert); if (!convert) return QVariant(); return retval; } return QString::fromAscii(val); } return strtod(val, 0); case QVariant::Date: if (val[0] == '\0') { return QVariant(QDate()); } else { #ifndef QT_NO_DATESTRING return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate)); #else return QVariant(QString::fromLatin1(val)); #endif } case QVariant::Time: { const QString str = QString::fromLatin1(val); #ifndef QT_NO_DATESTRING if (str.isEmpty()) return QVariant(QTime()); if (str.at(str.length() - 3) == QLatin1Char('+')) // strip the timezone return QVariant(QTime::fromString(str.left(str.length() - 3), Qt::ISODate)); return QVariant(QTime::fromString(str, Qt::ISODate)); #else return QVariant(str); #endif } case QVariant::DateTime: { QString dtval = QString::fromLatin1(val); #ifndef QT_NO_DATESTRING if (dtval.length() < 10) return QVariant(QDateTime()); // remove the timezone if (dtval.at(dtval.length() - 3) == QLatin1Char('+')) dtval.chop(3); // milliseconds are sometimes returned with 2 digits only if (dtval.at(dtval.length() - 3).isPunct()) dtval += QLatin1Char('0'); if (dtval.isEmpty()) return QVariant(QDateTime()); else return QVariant(QDateTime::fromString(dtval, Qt::ISODate)); #else return QVariant(dtval); #endif } case QVariant::ByteArray: { size_t len; unsigned char *data = PQunescapeBytea((unsigned char*)val, &len); QByteArray ba((const char*)data, len); qPQfreemem(data); return QVariant(ba); } default: case QVariant::Invalid: qWarning("QPSQLResult::data: unknown data type"); } return QVariant(); }
unsigned char *postgresql_util_unescape_binary(const unsigned char *from, size_t *to_length) { return PQunescapeBytea(from, to_length); }
static int pgsql_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees ) { pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data; struct pdo_column_data *cols = stmt->columns; size_t tmp_len; if (!S->result) { return 0; } /* We have already increased count by 1 in pgsql_stmt_fetch() */ if (PQgetisnull(S->result, S->current_row - 1, colno)) { /* Check if we got NULL */ *ptr = NULL; *len = 0; } else { *ptr = PQgetvalue(S->result, S->current_row - 1, colno); *len = PQgetlength(S->result, S->current_row - 1, colno); switch (cols[colno].param_type) { case PDO_PARAM_INT: ZEND_ATOL(S->cols[colno].intval, *ptr); *ptr = (char *) &(S->cols[colno].intval); *len = sizeof(zend_long); break; case PDO_PARAM_BOOL: S->cols[colno].boolval = **ptr == 't' ? 1: 0; *ptr = (char *) &(S->cols[colno].boolval); *len = sizeof(zend_bool); break; case PDO_PARAM_LOB: if (S->cols[colno].pgsql_type == OIDOID) { /* ooo, a real large object */ char *end_ptr; Oid oid = (Oid)strtoul(*ptr, &end_ptr, 10); int loid = lo_open(S->H->server, oid, INV_READ); if (loid >= 0) { *ptr = (char*)pdo_pgsql_create_lob_stream(&stmt->database_object_handle, loid, oid); *len = 0; return *ptr ? 1 : 0; } *ptr = NULL; *len = 0; return 0; } else { char *tmp_ptr = (char *)PQunescapeBytea((unsigned char *)*ptr, &tmp_len); if (!tmp_ptr) { /* PQunescapeBytea returned an error */ *len = 0; return 0; } if (!tmp_len) { /* Empty string, return as empty stream */ *ptr = (char *)php_stream_memory_open(TEMP_STREAM_READONLY, "", 0); PQfreemem(tmp_ptr); *len = 0; } else { *ptr = estrndup(tmp_ptr, tmp_len); PQfreemem(tmp_ptr); *len = tmp_len; *caller_frees = 1; } } break; case PDO_PARAM_NULL: case PDO_PARAM_STR: case PDO_PARAM_STMT: case PDO_PARAM_INPUT_OUTPUT: case PDO_PARAM_ZVAL: default: break; } } return 1; }
/* * Convert a str to a db value, does not copy strings * The postgresql module uses a custom escape function for BLOBs. * If the _s is linked in the db_val result, it will be returned zero */ int db_postgres_str2val(const db_type_t _t, db_val_t* _v, const char* _s, const int _l) { static str dummy_string = {"", 0}; char *x; if (!_v) { LM_ERR("invalid parameter value\n"); return -1; } if (!_s) { memset(_v, 0, sizeof(db_val_t)); /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STR(_v) = dummy_string; VAL_TYPE(_v) = _t; VAL_NULL(_v) = 1; return 0; } VAL_NULL(_v) = 0; switch(_t) { case DB_INT: LM_DBG("converting INT [%s]\n", _s); if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("failed to convert INT value from string\n"); return -2; } else { VAL_TYPE(_v) = DB_INT; return 0; } break; case DB_BIGINT: LM_DBG("converting BIGINT [%s]\n", _s); if (db_str2bigint(_s, &VAL_BIGINT(_v)) < 0) { LM_ERR("failed to convert BIGINT value from string\n"); return -2; } else { VAL_TYPE(_v) = DB_BIGINT; return 0; } break; case DB_BITMAP: LM_DBG("converting BITMAP [%s]\n", _s); if (db_str2int(_s, &VAL_INT(_v)) < 0) { LM_ERR("failed to convert BITMAP value from string\n"); return -3; } else { VAL_TYPE(_v) = DB_BITMAP; return 0; } break; case DB_DOUBLE: LM_DBG("converting DOUBLE [%s]\n", _s); if (db_str2double(_s, &VAL_DOUBLE(_v)) < 0) { LM_ERR("failed to convert DOUBLE value from string\n"); return -4; } else { VAL_TYPE(_v) = DB_DOUBLE; return 0; } break; case DB_STRING: LM_DBG("converting STRING [%s]\n", _s); VAL_STRING(_v) = _s; VAL_TYPE(_v) = DB_STRING; VAL_FREE(_v) = 1; return 0; case DB_STR: LM_DBG("converting STR [%.*s]\n", _l, _s); VAL_STR(_v).s = (char*)_s; VAL_STR(_v).len = _l; VAL_TYPE(_v) = DB_STR; VAL_FREE(_v) = 1; return 0; case DB_DATETIME: LM_DBG("converting DATETIME [%s]\n", _s); if (db_str2time(_s, &VAL_TIME(_v)) < 0) { LM_ERR("failed to convert datetime\n"); return -5; } else { VAL_TYPE(_v) = DB_DATETIME; return 0; } break; case DB_BLOB: LM_DBG("converting BLOB [%.*s]\n", _l, _s); /* PQunescapeBytea: Converts a string representation of binary data * into binary data - the reverse of PQescapeBytea. * This is needed when retrieving bytea data in text format, * but not when retrieving it in binary format. */ x = (char*)PQunescapeBytea((unsigned char*)_s, (size_t*)(void*)&(VAL_BLOB(_v).len) ); VAL_BLOB(_v).s = pkg_malloc( VAL_BLOB(_v).len+1 ); if (VAL_BLOB(_v).s==NULL) { LM_ERR("failed to allocate pkg for BLOB\n"); return -6; } memcpy( VAL_BLOB(_v).s, x, VAL_BLOB(_v).len); VAL_BLOB(_v).s[VAL_BLOB(_v).len]='\0'; free(x); VAL_TYPE(_v) = DB_BLOB; VAL_FREE(_v) = 1; LM_DBG("got blob len %d\n", _l); return 0; } return -6; }
int main(int, char **) { PQescapeBytea(0, 0, 0); PQunescapeBytea(0, 0); return 0; }