/* * call-seq: * res.getvalue( tup_num, field_num ) * * Returns the value in tuple number _tup_num_, field _field_num_, * or +nil+ if the field is +NULL+. */ static VALUE pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num) { VALUE val; PGresult *result; int i = NUM2INT(tup_num); int j = NUM2INT(field_num); result = pgresult_get(self); if(i < 0 || i >= PQntuples(result)) { rb_raise(rb_eArgError,"invalid tuple number %d", i); } if(j < 0 || j >= PQnfields(result)) { rb_raise(rb_eArgError,"invalid field number %d", j); } if(PQgetisnull(result, i, j)) return Qnil; val = rb_tainted_str_new(PQgetvalue(result, i, j), PQgetlength(result, i, j)); #ifdef M17N_SUPPORTED /* associate client encoding for text format only */ if ( 0 == PQfformat(result, j) ) { ASSOCIATE_INDEX( val, self ); } else { rb_enc_associate( val, rb_ascii8bit_encoding() ); } #endif return val; }
VALUE pg_tmbc_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field ) { t_pg_coder *p_coder = NULL; t_pg_result *p_result = pgresult_get_this(result); t_tmbc *this = (t_tmbc *) p_typemap; t_typemap *default_tm; if (PQgetisnull(p_result->pgresult, tuple, field)) { return Qnil; } p_coder = this->convs[field].cconv; if( p_coder ){ char * val = PQgetvalue( p_result->pgresult, tuple, field ); int len = PQgetlength( p_result->pgresult, tuple, field ); if( p_coder->dec_func ){ return p_coder->dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result)); } else { t_pg_coder_dec_func dec_func; dec_func = pg_coder_dec_func( p_coder, PQfformat(p_result->pgresult, field) ); return dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result)); } } default_tm = DATA_PTR( this->typemap.default_typemap ); return default_tm->funcs.typecast_result_value( default_tm, result, tuple, field ); }
/* * Make a Ruby array out of the encoded values from the specified * column in the given result. */ static VALUE make_column_result_array( VALUE self, int col ) { PGresult *result = pgresult_get( self ); int rows = PQntuples( result ); int i; VALUE val = Qnil; VALUE results = rb_ary_new2( rows ); if ( col >= PQnfields(result) ) rb_raise( rb_eIndexError, "no column %d in result", col ); for ( i=0; i < rows; i++ ) { val = rb_tainted_str_new( PQgetvalue(result, i, col), PQgetlength(result, i, col) ); #ifdef M17N_SUPPORTED /* associate client encoding for text format only */ if ( 0 == PQfformat(result, col) ) { ASSOCIATE_INDEX( val, self ); } else { rb_enc_associate( val, rb_ascii8bit_encoding() ); } #endif rb_ary_store( results, i, val ); } return results; }
/** Determine the format of timestamps used by the server. * A PostgresSQL server can be configured to store timestamps either as 8-byte * integers or floating point numbers with double precision. This functions * sends a simple SQL query to the server and tries to determine the format of * timestamps from the reply. This function is executed once after connecting * to a PostgreSQL server and the result of the detection is then stored in * form of a flag in pg_con connection structure. * @param con A PostgreSQL connection handle * @retval 0 If the server stores timestamps as floating point numbers. * @retval 1 If the server stores timestamps as 8-byte integers. * @retval A negative number on error. */ static int timestamp_format(PGconn *con) { unsigned long long offset; PGresult *res = 0; char *val; str sql; if(build_timestamp_format_sql(&sql) != 0) { ERR("postgres: Error while building SQL query to obtain timestamp " "format\n"); return -1; } res = PQexecParams(con, sql.s, 0, 0, 0, 0, 0, 1); pkg_free(sql.s); if(PQfformat(res, 0) != 1) { ERR("postgres: Binary format expected but server sent text\n"); goto error; } if(PQntuples(res) != 1) { ERR("postgres: Only one column expected, %d received\n", PQntuples(res)); goto error; } if(PQnfields(res) != 1) { ERR("postgres: Only one row expected, %d received\n", PQnfields(res)); goto error; } val = PQgetvalue(res, 0, 0); offset = ((unsigned long long)ntohl(((unsigned int *)val)[0]) << 32) + ntohl(((unsigned int *)val)[1]); PQclear(res); /* Server using int8 timestamps would return 1000000, because it stores * timestamps in microsecond resolution across the whole range. Server * using double timestamps would return 1 (encoded as double) here because * subsection fraction is stored as fractional part in the IEEE * representation. 1 stored as double would result in 4607182418800017408 * when the memory location occupied by the variable is read as unsigned * long long. */ if(offset == 1000000) { DBG("postgres: Server uses int8 format for timestamps.\n"); return 1; } else { DBG("postgres: Server uses double format for timestamps.\n"); return 0; } error: PQclear(res); return -1; }
/* * call-seq: * res.fformat( column_number ) -> Fixnum * * Returns the format (0 for text, 1 for binary) of column * _column_number_. * * Raises ArgumentError if _column_number_ is out of range. */ static VALUE pgresult_fformat(VALUE self, VALUE column_number) { PGresult *result = pgresult_get(self); int fnumber = NUM2INT(column_number); if (fnumber < 0 || fnumber >= PQnfields(result)) { rb_raise(rb_eArgError, "Column number is out of range: %d", fnumber); } return INT2FIX(PQfformat(result, fnumber)); }
int evsql_result_field (const struct evsql_result *res, size_t row, size_t col, const char **ptr, size_t *size) { *ptr = NULL; switch (res->evsql->type) { case EVSQL_EVPQ: if (PQfformat(res->result.pq, col) != 1) ERROR("[%zu:%zu] PQfformat is not binary: %d", row, col, PQfformat(res->result.pq, col)); *size = PQgetlength(res->result.pq, row, col); *ptr = PQgetvalue(res->result.pq, row, col); return 0; default: FATAL("res->evsql->type"); } error: return -1; }
/* Processes one tuple of the snapshot query result set. */ int snapshot_tuple(client_context_t context, PGresult *res, int row_number) { if (PQnfields(res) != 1) { client_error(context, "Unexpected response with %d fields", PQnfields(res)); return EIO; } if (PQgetisnull(res, row_number, 0)) { client_error(context, "Unexpected null response value"); return EIO; } if (PQfformat(res, 0) != 1) { /* format 1 == binary */ client_error(context, "Unexpected response format: %d", PQfformat(res, 0)); return EIO; } /* wal_pos == 0 == InvalidXLogRecPtr */ int err = parse_frame(context->repl.frame_reader, 0, PQgetvalue(res, row_number, 0), PQgetlength(res, row_number, 0)); if (err) { client_error(context, "Error parsing frame data: %s", avro_strerror()); } return err; }
bool ResultSet::isColumnBinaryFormat(int column_idx) { //Raise an error in case the column index is invalid if(column_idx < 0 || column_idx >= getColumnCount()) throw Exception(ERR_REF_TUPLE_COL_INV_INDEX, __PRETTY_FUNCTION__, __FILE__, __LINE__); /* Returns the column format in the current tuple. According to libpq documentation, value = 0, indicates column text format, value = 1 the column has binary format, the other values are reserved. One additional check is made, if the type of the column is bytea. */ return(PQfformat(sql_result, column_idx)==1 || PQftype(sql_result, column_idx)==BYTEAOID); }
bool ResultSet::isColumnBinaryFormat(const QString &column_name) { int col_idx=-1; try { col_idx=getColumnIndex(column_name); } catch(Exception &e) { throw Exception(e.getErrorMessage(), e.getErrorType(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e); } /* Returns the column format in the current tuple. According to libpq documentation, value = 0, indicates column text format, value = 1 the column has binary format, the other values are reserved */ return(PQfformat(sql_result, col_idx)==1); }
/* * call-seq: * res.values -> Array * * Returns all tuples as an array of arrays. */ static VALUE pgresult_values(VALUE self) { PGresult* result = (PGresult*) pgresult_get(self); int row; int field; int num_rows = PQntuples(result); int num_fields = PQnfields(result); VALUE ary = rb_ary_new2(num_rows); for ( row = 0; row < num_rows; row++ ) { VALUE new_row = rb_ary_new2(num_fields); /* populate the row */ for ( field = 0; field < num_fields; field++ ) { if ( PQgetisnull(result, row, field) ) { rb_ary_store( new_row, field, Qnil ); } else { VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field), PQgetlength(result, row, field) ); #ifdef M17N_SUPPORTED /* associate client encoding for text format only */ if ( 0 == PQfformat(result, field) ) { ASSOCIATE_INDEX( val, self ); } else { rb_enc_associate( val, rb_ascii8bit_encoding() ); } #endif rb_ary_store( new_row, field, val ); } } rb_ary_store( ary, row, new_row ); } return ary; }
static VALUE pg_tmas_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field ) { VALUE ret; char * val; int len; t_pg_result *p_result = pgresult_get_this(result); if (PQgetisnull(p_result->pgresult, tuple, field)) { return Qnil; } val = PQgetvalue( p_result->pgresult, tuple, field ); len = PQgetlength( p_result->pgresult, tuple, field ); if ( 0 == PQfformat(p_result->pgresult, field) ) { ret = pg_text_dec_string(NULL, val, len, tuple, field, ENCODING_GET(result)); } else { ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, ENCODING_GET(result)); } return ret; }
static VALUE pgresult_value(VALUE self, PGresult *result, int tuple_num, int field_num) { VALUE val; if ( PQgetisnull(result, tuple_num, field_num) ) { return Qnil; } else { val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ), PQgetlength(result, tuple_num, field_num) ); #ifdef M17N_SUPPORTED /* associate client encoding for text format only */ if ( 0 == PQfformat(result, field_num) ) { ASSOCIATE_INDEX( val, self ); } else { rb_enc_associate( val, rb_ascii8bit_encoding() ); } #endif return val; } }
/* * call-seq: * res[ n ] -> Hash * * Returns tuple _n_ as a hash. */ static VALUE pgresult_aref(VALUE self, VALUE index) { PGresult *result = pgresult_get(self); int tuple_num = NUM2INT(index); int field_num; VALUE fname,val; VALUE tuple; if ( tuple_num < 0 || tuple_num >= PQntuples(result) ) rb_raise( rb_eIndexError, "Index %d is out of range", tuple_num ); tuple = rb_hash_new(); for ( field_num = 0; field_num < PQnfields(result); field_num++ ) { fname = rb_tainted_str_new2( PQfname(result,field_num) ); ASSOCIATE_INDEX(fname, self); if ( PQgetisnull(result, tuple_num, field_num) ) { rb_hash_aset( tuple, fname, Qnil ); } else { val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ), PQgetlength(result, tuple_num, field_num) ); #ifdef M17N_SUPPORTED /* associate client encoding for text format only */ if ( 0 == PQfformat(result, field_num) ) { ASSOCIATE_INDEX( val, self ); } else { rb_enc_associate( val, rb_ascii8bit_encoding() ); } #endif rb_hash_aset( tuple, fname, val ); } } return tuple; }
bool ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno, enum ECPGttype type, enum ECPGttype ind_type, char *var, char *ind, long varcharsize, long offset, long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator) { struct sqlca_t *sqlca = ECPGget_sqlca(); char *pval = (char *) PQgetvalue(results, act_tuple, act_field); int binary = PQfformat(results, act_field); int size = PQgetlength(results, act_tuple, act_field); int value_for_indicator = 0; long log_offset; /* * If we are running in a regression test, do not log the offset variable, * it depends on the machine's alignment. */ if (ecpg_internal_regression_mode) log_offset = -1; else log_offset = offset; ecpg_log("ecpg_get_data on line %d: RESULT: %s offset: %ld; array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, ECPG_IS_ARRAY(isarray) ? "yes" : "no"); /* pval is a pointer to the value */ if (!pval) { /* * This should never happen because we already checked that we found * at least one tuple, but let's play it safe. */ ecpg_raise(lineno, ECPG_NOT_FOUND, ECPG_SQLSTATE_NO_DATA, NULL); return (false); } /* We will have to decode the value */ /* * check for null value and set indicator accordingly, i.e. -1 if NULL and * 0 if not */ if (PQgetisnull(results, act_tuple, act_field)) value_for_indicator = -1; switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #ifdef HAVE_LONG_LONG_INT case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #endif /* HAVE_LONG_LONG_INT */ case ECPGt_NO_INDICATOR: if (value_for_indicator == -1) { if (force_indicator == false) { /* * Informix has an additional way to specify NULLs note * that this uses special values to denote NULL */ ECPGset_noind_null(type, var + offset * act_tuple); } else { ecpg_raise(lineno, ECPG_MISSING_INDICATOR, ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER, NULL); return (false); } } break; default: ecpg_raise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ecpg_type_name(ind_type)); return (false); break; } if (value_for_indicator == -1) return (true); /* let's check if it really is an array if it should be one */ if (isarray == ECPG_ARRAY_ARRAY) { if (*pval != '{') { ecpg_raise(lineno, ECPG_DATA_NOT_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL); return (false); } switch (type) { case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_varchar: case ECPGt_string: break; default: pval++; break; } } do { if (binary) { if (varcharsize == 0 || varcharsize * offset >= size) memcpy(var + offset * act_tuple, pval, size); else { memcpy(var + offset * act_tuple, pval, varcharsize * offset); if (varcharsize * offset < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } else { switch (type) { long res; unsigned long ures; double dres; char *scan_length; numeric *nres; date ddres; timestamp tres; interval *ires; case ECPGt_short: case ECPGt_int: case ECPGt_long: res = strtol(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; switch (type) { case ECPGt_short: *((short *) (var + offset * act_tuple)) = (short) res; break; case ECPGt_int: *((int *) (var + offset * act_tuple)) = (int) res; break; case ECPGt_long: *((long *) (var + offset * act_tuple)) = (long) res; break; default: /* Cannot happen */ break; } break; case ECPGt_unsigned_short: case ECPGt_unsigned_int: case ECPGt_unsigned_long: ures = strtoul(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; switch (type) { case ECPGt_unsigned_short: *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures; break; case ECPGt_unsigned_int: *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures; break; case ECPGt_unsigned_long: *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures; break; default: /* Cannot happen */ break; } break; #ifdef HAVE_LONG_LONG_INT #ifdef HAVE_STRTOLL case ECPGt_long_long: *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; break; #endif /* HAVE_STRTOLL */ #ifdef HAVE_STRTOULL case ECPGt_unsigned_long_long: *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10); if ((isarray && *scan_length != ',' && *scan_length != '}') || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */ { ecpg_raise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; break; #endif /* HAVE_STRTOULL */ #endif /* HAVE_LONG_LONG_INT */ case ECPGt_float: case ECPGt_double: if (isarray && *pval == '"') pval++; if (!check_special_value(pval, &dres, &scan_length)) dres = strtod(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_FLOAT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; switch (type) { case ECPGt_float: *((float *) (var + offset * act_tuple)) = dres; break; case ECPGt_double: *((double *) (var + offset * act_tuple)) = dres; break; default: /* Cannot happen */ break; } break; case ECPGt_bool: if (pval[0] == 'f' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = false; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = false; else ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL); pval++; break; } else if (pval[0] == 't' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = true; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = true; else ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL); pval++; break; } else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field)) { /* NULL is valid */ break; } ecpg_raise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); break; case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_string: { char *str = (char *) (var + offset * act_tuple); /* * If varcharsize is unknown and the offset is that of * char *, then this variable represents the array of * character pointers. So, use extra indirection. */ if (varcharsize == 0 && offset == sizeof(char *)) str = *(char **)str; if (varcharsize == 0 || varcharsize > size) { strncpy(str, pval, size + 1); /* do the rtrim() */ if (type == ECPGt_string) { char *last = str + size; while (last > str && (*last == ' ' || *last == '\0')) { *last = '\0'; last--; } } } else { strncpy(str, pval, varcharsize); if (varcharsize < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } break; case ECPGt_varchar: { struct ECPGgeneric_varchar *variable = (struct ECPGgeneric_varchar *) (var + offset * act_tuple); variable->len = size; if (varcharsize == 0) strncpy(variable->arr, pval, variable->len); else { strncpy(variable->arr, pval, varcharsize); if (variable->len > varcharsize) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = variable->len; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = variable->len; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = variable->len; break; #ifdef HAVE_LONG_LONG_INT case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = variable->len; break; #endif /* HAVE_LONG_LONG_INT */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; variable->len = varcharsize; } } pval += size; } break; case ECPGt_decimal: case ECPGt_numeric: if (isarray && *pval == '"') nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length); else nres = PGTYPESnumeric_from_asc(pval, &scan_length); /* did we get an error? */ if (nres == NULL) { ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here instead * of an error */ nres = PGTYPESnumeric_new(); if (nres) ECPGset_noind_null(ECPGt_numeric, nres); else { ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); return (false); } } else { ecpg_raise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(nres); ecpg_raise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; if (type == ECPGt_numeric) PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple)); else PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple)); PGTYPESnumeric_free(nres); break; case ECPGt_interval: if (isarray && *pval == '"') ires = PGTYPESinterval_from_asc(pval + 1, &scan_length); else ires = PGTYPESinterval_from_asc(pval, &scan_length); /* did we get an error? */ if (ires == NULL) { ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here instead * of an error */ ires = (interval *) ecpg_alloc(sizeof(interval), lineno); if (!ires) return (false); ECPGset_noind_null(ECPGt_interval, ires); } else { ecpg_raise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(ires); ecpg_raise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple)); free(ires); break; case ECPGt_date: if (isarray && *pval == '"') ddres = PGTYPESdate_from_asc(pval + 1, &scan_length); else ddres = PGTYPESdate_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here instead * of an error */ ECPGset_noind_null(ECPGt_date, &ddres); } else { ecpg_raise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((date *) (var + offset * act_tuple)) = ddres; pval = scan_length; break; case ECPGt_timestamp: if (isarray && *pval == '"') tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length); else tres = PGTYPEStimestamp_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { ecpg_log("ecpg_get_data on line %d: RESULT %s; errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here instead * of an error */ ECPGset_noind_null(ECPGt_timestamp, &tres); } else { ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ecpg_raise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((timestamp *) (var + offset * act_tuple)) = tres; pval = scan_length; break; default: ecpg_raise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ecpg_type_name(type)); return (false); break; } if (ECPG_IS_ARRAY(isarray)) { bool string = false; /* set array to next entry */ ++act_tuple; /* set pval to the next entry */ /* * *pval != '\0' should not be needed, but is used as a safety * guard */ for (; *pval != '\0' && (string || (!array_delimiter(isarray, *pval) && !array_boundary(isarray, *pval))); ++pval) if (*pval == '"') string = string ? false : true; if (array_delimiter(isarray, *pval)) ++pval; } } } while (*pval != '\0' && !array_boundary(isarray, *pval)); return (true); }
/* * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int4 -- offset within the file * chunk bytea -- file content * */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) { fprintf(stderr, "could not send query: %s\n", PQerrorMessage(conn)); exit(1); } if (verbose) fprintf(stderr, "getting chunks: %s\n", sql); if (PQsetSingleRowMode(conn) != 1) { fprintf(stderr, "could not set libpq connection to single row mode\n"); exit(1); } if (verbose) fprintf(stderr, "sent query\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int chunkoff; int chunksize; char *chunk; switch(PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: continue; /* final zero-row result */ default: fprintf(stderr, "unexpected result while fetching remote files: %s\n", PQresultErrorMessage(res)); exit(1); } /* sanity check the result set */ if (!(PQnfields(res) == 3 && PQntuples(res) == 1)) { fprintf(stderr, "unexpected result set size while fetching remote files\n"); exit(1); } if (!(PQftype(res, 0) == TEXTOID && PQftype(res, 1) == INT4OID && PQftype(res, 2) == BYTEAOID)) { fprintf(stderr, "unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); exit(1); } if (!(PQfformat(res, 0) == 1 && PQfformat(res, 1) == 1 && PQfformat(res, 2) == 1)) { fprintf(stderr, "unexpected result format while fetching remote files\n"); exit(1); } if (!(!PQgetisnull(res, 0, 0) && !PQgetisnull(res, 0, 1) && !PQgetisnull(res, 0, 2) && PQgetlength(res, 0, 1) == sizeof(int32))) { fprintf(stderr, "unexpected result set while fetching remote files\n"); exit(1); } /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int32)); chunkoff = ntohl(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); if (verbose) fprintf(stderr, "received chunk for file \"%s\", off %d, len %d\n", filename, chunkoff, chunksize); open_target_file(filename, false); write_file_range(chunk, chunkoff, chunksize); } }
/*---- * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int8 -- offset within the file * chunk bytea -- file content *---- */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) pg_fatal("could not send query: %s", PQerrorMessage(conn)); pg_log(PG_DEBUG, "getting file chunks\n"); if (PQsetSingleRowMode(conn) != 1) pg_fatal("could not set libpq connection to single row mode\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int64 chunkoff; char chunkoff_str[32]; int chunksize; char *chunk; switch (PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: PQclear(res); continue; /* final zero-row result */ default: pg_fatal("unexpected result while fetching remote files: %s", PQresultErrorMessage(res)); } /* sanity check the result set */ if (PQnfields(res) != 3 || PQntuples(res) != 1) pg_fatal("unexpected result set size while fetching remote files\n"); if (PQftype(res, 0) != TEXTOID || PQftype(res, 1) != INT8OID || PQftype(res, 2) != BYTEAOID) { pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); } if (PQfformat(res, 0) != 1 && PQfformat(res, 1) != 1 && PQfformat(res, 2) != 1) { pg_fatal("unexpected result format while fetching remote files\n"); } if (PQgetisnull(res, 0, 0) || PQgetisnull(res, 0, 1)) { pg_fatal("unexpected null values in result while fetching remote files\n"); } if (PQgetlength(res, 0, 1) != sizeof(int64)) pg_fatal("unexpected result length while fetching remote files\n"); /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int64)); chunkoff = pg_recvint64(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); /* * If a file has been deleted on the source, remove it on the target * as well. Note that multiple unlink() calls may happen on the same * file if multiple data chunks are associated with it, hence ignore * unconditionally anything missing. If this file is not a relation * data file, then it has been already truncated when creating the * file chunk list at the previous execution of the filemap. */ if (PQgetisnull(res, 0, 2)) { pg_log(PG_DEBUG, "received null value for chunk for file \"%s\", file has been deleted\n", filename); remove_target_file(filename, true); pg_free(filename); PQclear(res); continue; } /* * Separate step to keep platform-dependent format code out of * translatable strings. */ snprintf(chunkoff_str, sizeof(chunkoff_str), INT64_FORMAT, chunkoff); pg_log(PG_DEBUG, "received chunk for file \"%s\", offset %s, size %d\n", filename, chunkoff_str, chunksize); open_target_file(filename, false); write_target_range(chunk, chunkoff, chunksize); pg_free(filename); PQclear(res); } }
PGresult * pqt_copyresult(PGtypeArgs *args, int nattrs) { int i; PGresult *res; int tableid, columnid, format; PGresAttDesc *ad = (PGresAttDesc *) malloc(nattrs * sizeof(PGresAttDesc)); if (!ad) { PQseterror(args->err, PQT_OUTOFMEMORY); return NULL; } tableid = PQftable(args->get.result, args->get.field_num); columnid = PQftablecol(args->get.result, args->get.field_num); format = PQfformat(args->get.result, args->get.field_num); for (i=0; i < nattrs; i++) { ad[i].tableid = tableid; ad[i].columnid = columnid; ad[i].format = format; /* simple array */ if (args->typhandler->nattrs == 0) { ad[i].typid = args->typhandler->typoid; ad[i].typlen = args->typhandler->typlen; ad[i].name = NULL; ad[i].atttypmod = -1; } /* composite/record */ else { ad[i].typid = args->typhandler->attDescs[i].attoid; ad[i].typlen = args->typhandler->attDescs[i].attlen; ad[i].name = args->typhandler->attDescs[i].attname; ad[i].atttypmod = args->typhandler->attDescs[i].atttypmod; } } res = PQcopyResult(args->get.result, PG_COPYRES_EVENTS | PG_COPYRES_NOTICEHOOKS); if (!res) { free(ad); PQseterror(args->err, PQT_OUTOFMEMORY); return NULL; } if (!PQsetResultAttrs(res, nattrs, ad)) { PQclear(res); PQseterror(args->err, PQT_OUTOFMEMORY); res = NULL; } free(ad); return res; }
/*---- * Runs a query, which returns pieces of files from the remote source data * directory, and overwrites the corresponding parts of target files with * the received parts. The result set is expected to be of format: * * path text -- path in the data directory, e.g "base/1/123" * begin int4 -- offset within the file * chunk bytea -- file content *---- */ static void receiveFileChunks(const char *sql) { PGresult *res; if (PQsendQueryParams(conn, sql, 0, NULL, NULL, NULL, NULL, 1) != 1) pg_fatal("could not send query: %s", PQerrorMessage(conn)); pg_log(PG_DEBUG, "getting file chunks\n"); if (PQsetSingleRowMode(conn) != 1) pg_fatal("could not set libpq connection to single row mode\n"); while ((res = PQgetResult(conn)) != NULL) { char *filename; int filenamelen; int chunkoff; int chunksize; char *chunk; switch (PQresultStatus(res)) { case PGRES_SINGLE_TUPLE: break; case PGRES_TUPLES_OK: PQclear(res); continue; /* final zero-row result */ default: pg_fatal("unexpected result while fetching remote files: %s", PQresultErrorMessage(res)); } /* sanity check the result set */ if (PQnfields(res) != 3 || PQntuples(res) != 1) pg_fatal("unexpected result set size while fetching remote files\n"); if (PQftype(res, 0) != TEXTOID && PQftype(res, 1) != INT4OID && PQftype(res, 2) != BYTEAOID) { pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u\n", PQftype(res, 0), PQftype(res, 1), PQftype(res, 2)); } if (PQfformat(res, 0) != 1 && PQfformat(res, 1) != 1 && PQfformat(res, 2) != 1) { pg_fatal("unexpected result format while fetching remote files\n"); } if (PQgetisnull(res, 0, 0) || PQgetisnull(res, 0, 1)) { pg_fatal("unexpected null values in result while fetching remote files\n"); } if (PQgetlength(res, 0, 1) != sizeof(int32)) pg_fatal("unexpected result length while fetching remote files\n"); /* Read result set to local variables */ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int32)); chunkoff = ntohl(chunkoff); chunksize = PQgetlength(res, 0, 2); filenamelen = PQgetlength(res, 0, 0); filename = pg_malloc(filenamelen + 1); memcpy(filename, PQgetvalue(res, 0, 0), filenamelen); filename[filenamelen] = '\0'; chunk = PQgetvalue(res, 0, 2); /* * It's possible that the file was deleted on remote side after we * created the file map. In this case simply ignore it, as if it was * not there in the first place, and move on. */ if (PQgetisnull(res, 0, 2)) { pg_log(PG_DEBUG, "received null value for chunk for file \"%s\", file has been deleted\n", filename); pg_free(filename); PQclear(res); continue; } pg_log(PG_DEBUG, "received chunk for file \"%s\", offset %d, size %d\n", filename, chunkoff, chunksize); open_target_file(filename, false); write_target_range(chunk, chunkoff, chunksize); pg_free(filename); PQclear(res); } }
bool ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, enum ECPGttype type, enum ECPGttype ind_type, char *var, char *ind, long varcharsize, long offset, long ind_offset, enum ARRAY_TYPE isarray, enum COMPAT_MODE compat, bool force_indicator) { struct sqlca_t *sqlca = ECPGget_sqlca(); char *pval = (char *) PQgetvalue(results, act_tuple, act_field); int binary = PQfformat(results, act_field); int size = PQgetlength(results, act_tuple, act_field); int value_for_indicator = 0; long log_offset; /* * use a global variable to see if the environment variable * ECPG_REGRESSION is set or not. Remember the state in order to avoid * subsequent calls to getenv() for this purpose. */ if (ECPG_regression_mode == NOT_CHECKED) { if (getenv("ECPG_REGRESSION")) ECPG_regression_mode = REGRESS; else ECPG_regression_mode = NORMAL; } /* * If we are running in a regression test, do not log the offset variable, * it depends on the machine's alignment. */ if (ECPG_regression_mode == REGRESS) log_offset = -1; else log_offset = offset; ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld array: %s\n", lineno, pval ? (binary ? "BINARY" : pval) : "EMPTY", log_offset, isarray ? "Yes" : "No"); /* We will have to decode the value */ /* * check for null value and set indicator accordingly, i.e. -1 if NULL and * 0 if not */ if (PQgetisnull(results, act_tuple, act_field)) value_for_indicator = -1; switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = value_for_indicator; break; #endif /* HAVE_LONG_LONG_INT_64 */ case ECPGt_NO_INDICATOR: if (value_for_indicator == -1) { if (force_indicator == false) { /* * Informix has an additional way to specify NULLs note * that this uses special values to denote NULL */ ECPGset_noind_null(type, var + offset * act_tuple); } else { ECPGraise(lineno, ECPG_MISSING_INDICATOR, ECPG_SQLSTATE_NULL_VALUE_NO_INDICATOR_PARAMETER, NULL); return (false); } } break; default: ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(ind_type)); return (false); break; } if (value_for_indicator == -1) return (true); /* pval is a pointer to the value */ /* let's check if it really is an array if it should be one */ if (isarray == ECPG_ARRAY_ARRAY) { if (!pval || *pval != '{') { ECPGraise(lineno, ECPG_DATA_NOT_ARRAY, ECPG_SQLSTATE_DATATYPE_MISMATCH, NULL); return (false); } switch (type) { case ECPGt_char: case ECPGt_unsigned_char: case ECPGt_varchar: break; default: pval++; break; } } do { if (binary) { if (pval) { if (varcharsize == 0 || varcharsize * offset >= size) memcpy((char *) ((long) var + offset * act_tuple), pval, size); else { memcpy((char *) ((long) var + offset * act_tuple), pval, varcharsize * offset); if (varcharsize * offset < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } } else { switch (type) { long res; unsigned long ures; double dres; char *scan_length; numeric *nres; date ddres; timestamp tres; interval *ires; case ECPGt_short: case ECPGt_int: case ECPGt_long: if (pval) { res = strtol(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else res = 0L; switch (type) { case ECPGt_short: *((short *) (var + offset * act_tuple)) = (short) res; break; case ECPGt_int: *((int *) (var + offset * act_tuple)) = (int) res; break; case ECPGt_long: *((long *) (var + offset * act_tuple)) = (long) res; break; default: /* Cannot happen */ break; } break; case ECPGt_unsigned_short: case ECPGt_unsigned_int: case ECPGt_unsigned_long: if (pval) { ures = strtoul(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else ures = 0L; switch (type) { case ECPGt_unsigned_short: *((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures; break; case ECPGt_unsigned_int: *((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures; break; case ECPGt_unsigned_long: *((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures; break; default: /* Cannot happen */ break; } break; #ifdef HAVE_LONG_LONG_INT_64 #ifdef HAVE_STRTOLL case ECPGt_long_long: if (pval) { *((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10); if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_INT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else *((long long int *) (var + offset * act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOLL */ #ifdef HAVE_STRTOULL case ECPGt_unsigned_long_long: if (pval) { *((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10); if ((isarray && *scan_length != ',' && *scan_length != '}') || (!isarray && !(INFORMIX_MODE(compat) && *scan_length == '.') && *scan_length != '\0' && *scan_length != ' ')) /* Garbage left */ { ECPGraise(lineno, ECPG_UINT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else *((unsigned long long int *) (var + offset * act_tuple)) = (long long) 0; break; #endif /* HAVE_STRTOULL */ #endif /* HAVE_LONG_LONG_INT_64 */ case ECPGt_float: case ECPGt_double: if (pval) { if (isarray && *pval == '"') dres = strtod(pval + 1, &scan_length); else dres = strtod(pval, &scan_length); if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_FLOAT_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } pval = scan_length; } else dres = 0.0; switch (type) { case ECPGt_float: *((float *) (var + offset * act_tuple)) = dres; break; case ECPGt_double: *((double *) (var + offset * act_tuple)) = dres; break; default: /* Cannot happen */ break; } break; case ECPGt_bool: if (pval) { if (pval[0] == 'f' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = false; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = false; else ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size"); break; } else if (pval[0] == 't' && pval[1] == '\0') { if (offset == sizeof(char)) *((char *) (var + offset * act_tuple)) = true; else if (offset == sizeof(int)) *((int *) (var + offset * act_tuple)) = true; else ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, "different size"); break; } else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field)) { /* NULL is valid */ break; } } ECPGraise(lineno, ECPG_CONVERT_BOOL, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); break; case ECPGt_char: case ECPGt_unsigned_char: if (pval) { if (varcharsize == 0 || varcharsize > size) strncpy((char *) ((long) var + offset * act_tuple), pval, size + 1); else { strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize); if (varcharsize < size) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + ind_offset * act_tuple)) = size; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + ind_offset * act_tuple)) = size; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = size; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; } } pval += size; } break; case ECPGt_varchar: if (pval) { struct ECPGgeneric_varchar *variable = (struct ECPGgeneric_varchar *) ((long) var + offset * act_tuple); variable->len = size; if (varcharsize == 0) strncpy(variable->arr, pval, variable->len); else { strncpy(variable->arr, pval, varcharsize); if (variable->len > varcharsize) { /* truncation */ switch (ind_type) { case ECPGt_short: case ECPGt_unsigned_short: *((short *) (ind + offset * act_tuple)) = variable->len; break; case ECPGt_int: case ECPGt_unsigned_int: *((int *) (ind + offset * act_tuple)) = variable->len; break; case ECPGt_long: case ECPGt_unsigned_long: *((long *) (ind + offset * act_tuple)) = variable->len; break; #ifdef HAVE_LONG_LONG_INT_64 case ECPGt_long_long: case ECPGt_unsigned_long_long: *((long long int *) (ind + ind_offset * act_tuple)) = variable->len; break; #endif /* HAVE_LONG_LONG_INT_64 */ default: break; } sqlca->sqlwarn[0] = sqlca->sqlwarn[1] = 'W'; variable->len = varcharsize; } } pval += size; } break; case ECPGt_decimal: case ECPGt_numeric: if (pval) { if (isarray && *pval == '"') nres = PGTYPESnumeric_from_asc(pval + 1, &scan_length); else nres = PGTYPESnumeric_from_asc(pval, &scan_length); /* did we get an error? */ if (nres == NULL) { ECPGlog("ECPGget_data line %d: RESULT: %s errno %d\n", lineno, pval ? pval : "", errno); if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ nres = PGTYPESnumeric_new(); if (nres) ECPGset_noind_null(ECPGt_numeric, nres); else { ECPGraise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); return (false); } } else { ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(nres); ECPGraise(lineno, ECPG_NUMERIC_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; } else nres = PGTYPESnumeric_from_asc("0.0", &scan_length); if (type == ECPGt_numeric) PGTYPESnumeric_copy(nres, (numeric *) (var + offset * act_tuple)); else PGTYPESnumeric_to_decimal(nres, (decimal *) (var + offset * act_tuple)); free(nres); break; case ECPGt_interval: if (pval) { if (isarray && *pval == '"') ires = PGTYPESinterval_from_asc(pval + 1, &scan_length); else ires = PGTYPESinterval_from_asc(pval, &scan_length); /* did we get an error? */ if (ires == NULL) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ires = (interval *) ECPGalloc(sizeof(interval), lineno); if (!ires) return (false); ECPGset_noind_null(ECPGt_interval, ires); } else { ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { free(ires); ECPGraise(lineno, ECPG_INTERVAL_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } pval = scan_length; } else ires = PGTYPESinterval_from_asc("0 seconds", NULL); PGTYPESinterval_copy(ires, (interval *) (var + offset * act_tuple)); free(ires); break; case ECPGt_date: if (pval) { if (isarray && *pval == '"') ddres = PGTYPESdate_from_asc(pval + 1, &scan_length); else ddres = PGTYPESdate_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ECPGset_noind_null(ECPGt_date, &ddres); } else { ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_DATE_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((date *) (var + offset * act_tuple)) = ddres; pval = scan_length; } break; case ECPGt_timestamp: if (pval) { if (isarray && *pval == '"') tres = PGTYPEStimestamp_from_asc(pval + 1, &scan_length); else tres = PGTYPEStimestamp_from_asc(pval, &scan_length); /* did we get an error? */ if (errno != 0) { if (INFORMIX_MODE(compat)) { /* * Informix wants its own NULL value here * instead of an error */ ECPGset_noind_null(ECPGt_timestamp, &tres); } else { ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } else { if (isarray && *scan_length == '"') scan_length++; if (garbage_left(isarray, scan_length, compat)) { ECPGraise(lineno, ECPG_TIMESTAMP_FORMAT, ECPG_SQLSTATE_DATATYPE_MISMATCH, pval); return (false); } } *((timestamp *) (var + offset * act_tuple)) = tres; pval = scan_length; } break; default: ECPGraise(lineno, ECPG_UNSUPPORTED, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, ECPGtype_name(type)); return (false); break; } if (isarray == ECPG_ARRAY_ARRAY) { bool string = false; /* set array to next entry */ ++act_tuple; /* set pval to the next entry */ for (; string || (*pval != ',' && *pval != '}' && *pval != '\0'); ++pval) if (*pval == '"') string = string ? false : true; if (*pval == ',') ++pval; } else if (isarray == ECPG_ARRAY_VECTOR) { bool string = false; /* set array to next entry */ ++act_tuple; /* set pval to the next entry */ for (; string || (*pval != ' ' && *pval != '\0'); ++pval) if (*pval == '"') string = string ? false : true; if (*pval == ' ') ++pval; } } } while (*pval != '\0' && ((isarray == ECPG_ARRAY_ARRAY && *pval != '}') || isarray == ECPG_ARRAY_VECTOR)); return (true); }
int main(int argc, const char * const *argv) { char *args_string; char *member_id; char *image_type; const char *sql_member_image_params[2]; #ifndef PUBLIC_ACCESS #ifdef PUBLIC_AVATAR_ACCESS int authorization_required = 0; #endif char *cookies; regex_t session_ident_regex; ssize_t start, length; regmatch_t session_ident_regmatch[3]; char *session_ident; const char *sql_session_params[1]; #endif PGconn *conn; PGresult *dbr; args_string = getenv("QUERY_STRING"); if (!args_string) { fputs("Status: 403 Access Denied\n\n", stdout); return 0; } member_id = strtok(args_string, "+"); image_type = strtok(NULL, "+"); if (!member_id || !image_type) { fputs("Status: 403 Access Denied\n\n", stdout); return 0; } sql_member_image_params[0] = member_id; sql_member_image_params[1] = image_type; #ifndef PUBLIC_ACCESS #ifdef PUBLIC_AVATAR_ACCESS if (strcmp(image_type, "avatar")) { authorization_required = 1; #endif cookies = getenv("HTTP_COOKIE"); if (!args_string || !cookies) { fputs("Status: 403 Access Denied\n\n", stdout); return 0; } if (regcomp(&session_ident_regex, "(^|[; \t])liquid_feedback_session=([0-9A-Za-z]+)", REG_EXTENDED) != 0) { // shouldn't happen abort(); } if (regexec(&session_ident_regex, cookies, 3, session_ident_regmatch, 0) != 0) { fputs("Status: 403 Access Denied\n\n", stdout); return 0; } start = session_ident_regmatch[2].rm_so; length = session_ident_regmatch[2].rm_eo - session_ident_regmatch[2].rm_so; session_ident = malloc(length + 1); if (!session_ident) abort(); // shouldn't happen strncpy(session_ident, cookies + start, length); session_ident[length] = 0; sql_session_params[0] = session_ident; #ifdef PUBLIC_AVATAR_ACCESS } #endif #endif conn = PQconnectdb(GETPIC_CONNINFO); if (!conn) { fputs("Could not create PGconn structure.\n", stderr); return 1; } if (PQstatus(conn) != CONNECTION_OK) { fputs(PQerrorMessage(conn), stderr); PQfinish(conn); return 1; } #ifndef PUBLIC_ACCESS #ifdef PUBLIC_AVATAR_ACCESS if (authorization_required) { #endif dbr = PQexecParams(conn, "SELECT NULL FROM session JOIN member ON member.id = session.member_id WHERE session.ident = $1 AND member.active", 1, NULL, sql_session_params, NULL, NULL, 0 ); if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { fputs(PQresultErrorMessage(dbr), stderr); PQfinish(conn); return 1; } if (PQntuples(dbr) != 1) { fputs("Status: 403 Access Denied\n\n", stdout); PQfinish(conn); return 0; } #ifdef PUBLIC_AVATAR_ACCESS } #endif #endif dbr = PQexecParams(conn, "SELECT content_type, data " "FROM member_image " "WHERE member_id = $1 " "AND image_type = $2 " "AND scaled " "LIMIT 1;", 2, NULL, sql_member_image_params, NULL, NULL, 1 ); if (PQresultStatus(dbr) != PGRES_TUPLES_OK) { fputs(PQresultErrorMessage(dbr), stderr); PQfinish(conn); return 1; } if (PQntuples(dbr) == 0) { struct stat sb; PQclear(dbr); PQfinish(conn); fputs("Content-Type: image/jpeg\n\n", stdout); if (stat(GETPIC_DEFAULT_AVATAR, &sb)) return 1; fprintf(stdout, "Content-Length: %i\n", (int)sb.st_size); execl("/bin/cat", "cat", GETPIC_DEFAULT_AVATAR, NULL); return 1; } else { if (PQnfields(dbr) < 0) { fputs("Too few columns returned by database.\n", stderr); PQfinish(conn); return 1; } if (PQfformat(dbr, 0) != 1 || PQfformat(dbr, 1) != 1) { fputs("Database did not return data in binary format.\n", stderr); PQfinish(conn); return 1; } if (PQgetisnull(dbr, 0, 0) || PQgetisnull(dbr, 0, 1)) { fputs("Unexpected NULL in database result.\n", stderr); PQfinish(conn); return 1; } fprintf(stdout, "Content-Type: %s\n\n", PQgetvalue(dbr, 0, 0)); fwrite(PQgetvalue(dbr, 0, 1), PQgetlength(dbr, 0, 1), 1, stdout); } PQfinish(conn); return 0; }