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;
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
/*
 * 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;
}
Esempio n. 6
0
/*
 * 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;
}
Esempio n. 7
0
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 );
}