static VALUE pg_tmbc_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ) { t_tmbc *this = (t_tmbc *) p_typemap; t_pg_coder *p_coder; t_pg_coder_dec_func dec_func; if ( fieldno >= this->nfields || fieldno < 0 ) { rb_raise( rb_eArgError, "number of copy fields (%d) exceeds number of mapped columns (%d)", fieldno, this->nfields ); } p_coder = this->convs[fieldno].cconv; if( !p_coder ){ t_typemap *default_tm = DATA_PTR( this->typemap.default_typemap ); return default_tm->funcs.typecast_copy_get( default_tm, field_str, fieldno, format, enc_idx ); } dec_func = pg_coder_dec_func( p_coder, format ); /* Is it a pure String conversion? Then we can directly send field_str to the user. */ if( dec_func == pg_text_dec_string ){ PG_ENCODING_SET_NOCHECK( field_str, enc_idx ); return field_str; } if( dec_func == pg_bin_dec_bytea ){ PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() ); return field_str; } return dec_func( p_coder, RSTRING_PTR(field_str), RSTRING_LEN(field_str), 0, fieldno, enc_idx ); }
static VALUE pg_tmas_typecast_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ) { if( format == 0 ){ PG_ENCODING_SET_NOCHECK( field_str, enc_idx ); } else { PG_ENCODING_SET_NOCHECK( field_str, rb_ascii8bit_encindex() ); } return field_str; }
/* * Document-class: PG::TextDecoder::String < PG::SimpleDecoder * * This is a decoder class for conversion of PostgreSQL text output to * to Ruby String object. The output value will have the character encoding * set with PG::Connection#internal_encoding= . * */ VALUE pg_text_dec_string(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx) { VALUE ret = rb_tainted_str_new( val, len ); PG_ENCODING_SET_NOCHECK( ret, enc_idx ); return ret; }
/* * Result constructor */ VALUE pg_new_result(PGresult *result, VALUE rb_pgconn) { int nfields = result ? PQnfields(result) : 0; VALUE self = pgresult_s_allocate( rb_cPGresult ); t_pg_result *this; this = (t_pg_result *)xmalloc(sizeof(*this) + sizeof(*this->fnames) * nfields); DATA_PTR(self) = this; this->pgresult = result; this->connection = rb_pgconn; this->typemap = pg_typemap_all_strings; this->p_typemap = DATA_PTR( this->typemap ); this->autoclear = 0; this->nfields = -1; this->tuple_hash = Qnil; PG_ENCODING_SET_NOCHECK(self, ENCODING_GET(rb_pgconn)); if( result ){ t_pg_connection *p_conn = pg_get_connection(rb_pgconn); VALUE typemap = p_conn->type_map_for_results; /* Type check is done when assigned to PG::Connection. */ t_typemap *p_typemap = DATA_PTR(typemap); this->typemap = p_typemap->funcs.fit_to_result( typemap, self ); this->p_typemap = DATA_PTR( this->typemap ); } return self; }
/* * call-seq: * res.check -> nil * * Raises appropriate exception if PG::Result is in a bad state. */ VALUE pg_result_check( VALUE self ) { t_pg_result *this = pgresult_get_this(self); VALUE error, exception, klass; char * sqlstate; if(this->pgresult == NULL) { PGconn *conn = pg_get_pgconn(this->connection); error = rb_str_new2( PQerrorMessage(conn) ); } else { switch (PQresultStatus(this->pgresult)) { case PGRES_TUPLES_OK: case PGRES_COPY_OUT: case PGRES_COPY_IN: #ifdef HAVE_CONST_PGRES_COPY_BOTH case PGRES_COPY_BOTH: #endif #ifdef HAVE_CONST_PGRES_SINGLE_TUPLE case PGRES_SINGLE_TUPLE: #endif case PGRES_EMPTY_QUERY: case PGRES_COMMAND_OK: return self; case PGRES_BAD_RESPONSE: case PGRES_FATAL_ERROR: case PGRES_NONFATAL_ERROR: error = rb_str_new2( PQresultErrorMessage(this->pgresult) ); break; default: error = rb_str_new2( "internal error : unknown result status." ); } } PG_ENCODING_SET_NOCHECK( error, ENCODING_GET(self) ); sqlstate = PQresultErrorField( this->pgresult, PG_DIAG_SQLSTATE ); klass = lookup_error_class( sqlstate ); exception = rb_exc_new3( klass, error ); rb_iv_set( exception, "@connection", this->connection ); rb_iv_set( exception, "@result", this->pgresult ? self : Qnil ); rb_exc_raise( exception ); /* Not reached */ return self; }
/* * call-seq: * coder.encode( value [, encoding] ) * * Encodes the given Ruby object into string representation, without * sending data to/from the database server. * * A nil value is passed through. * */ static VALUE pg_coder_encode(int argc, VALUE *argv, VALUE self) { VALUE res; VALUE intermediate; VALUE value; int len, len2; int enc_idx; t_pg_coder *this = DATA_PTR(self); if(argc < 1 || argc > 2){ rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc); }else if(argc == 1){ enc_idx = rb_ascii8bit_encindex(); }else{ enc_idx = rb_to_encoding_index(argv[1]); } value = argv[0]; if( NIL_P(value) ) return Qnil; if( !this->enc_func ){ rb_raise(rb_eRuntimeError, "no encoder function defined"); } len = this->enc_func( this, value, NULL, &intermediate, enc_idx ); if( len == -1 ){ /* The intermediate value is a String that can be used directly. */ OBJ_INFECT(intermediate, value); return intermediate; } res = rb_str_new(NULL, len); PG_ENCODING_SET_NOCHECK(res, enc_idx); len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx ); if( len < len2 ){ rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)", rb_obj_classname( self ), len, len2 ); } rb_str_set_len( res, len2 ); OBJ_INFECT(res, value); RB_GC_GUARD(intermediate); return res; }
static VALUE pg_tmir_copy_get( t_typemap *p_typemap, VALUE field_str, int fieldno, int format, int enc_idx ) { t_tmir *this = (t_tmir *) p_typemap; rb_encoding *p_encoding = rb_enc_from_index(enc_idx); VALUE enc = rb_enc_from_encoding(p_encoding); /* field_str is reused in-place by pg_text_dec_copy_row(), so we need to make * a copy of the string buffer before used in ruby space. * This requires rb_str_new() instead of rb_str_dup() for Rubinius. */ VALUE field_str_copy = rb_str_new(RSTRING_PTR(field_str), RSTRING_LEN(field_str)); PG_ENCODING_SET_NOCHECK(field_str_copy, ENCODING_GET(field_str)); OBJ_INFECT(field_str_copy, field_str); return rb_funcall( this->self, s_id_typecast_copy_get, 4, field_str_copy, INT2NUM(fieldno), INT2NUM(format), enc ); }