ext/pg.h in pg-0.18.0.pre20140820094244 vs ext/pg.h in pg-0.18.0.pre20141017155815
- old
+ new
@@ -22,23 +22,42 @@
#endif
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
# include "ruby/encoding.h"
# define M17N_SUPPORTED
-# define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), pg_enc_get_index((index_holder)))
# ifdef HAVE_RB_ENCDB_ALIAS
extern int rb_encdb_alias(const char *, const char *);
# define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
# elif HAVE_RB_ENC_ALIAS
extern int rb_enc_alias(const char *, const char *);
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
# else
extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
# endif
+
+
+# if !defined(ENCODING_SET_INLINED)
+/* Rubinius doesn't define ENCODING_SET_INLINED, so we fall back to the more
+ * portable version.
+ */
+# define PG_ENCODING_SET_NOCHECK(obj,i) \
+ do { \
+ rb_enc_set_index((obj), (i)); \
+ } while(0)
+# else
+# define PG_ENCODING_SET_NOCHECK(obj,i) \
+ do { \
+ if ((i) < ENCODING_INLINE_MAX) \
+ ENCODING_SET_INLINED((obj), (i)); \
+ else \
+ rb_enc_set_index((obj), (i)); \
+ } while(0)
+# endif
+
#else
-# define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
+# define PG_ENCODING_SET_NOCHECK(obj,i) /* nothing */
#endif
#if RUBY_VM != 1
# define RUBY_18_COMPAT
#endif
@@ -64,10 +83,15 @@
# include "rubyio.h"
#else
# include "ruby/io.h"
#endif
+#ifdef RUBINIUS
+ /* Workaround for wrong FIXNUM_MAX definition */
+ typedef intptr_t native_int;
+#endif
+
#ifndef timeradd
#define timeradd(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
@@ -95,14 +119,105 @@
#include "libpq/libpq-fs.h" /* large-object interface */
#include "pg_config_manual.h"
#if defined(_WIN32)
# include <fcntl.h>
-__declspec(dllexport)
typedef long suseconds_t;
#endif
+/* The data behind each PG::Connection object */
+typedef struct {
+ PGconn *pgconn;
+
+ /* Cached IO object for the socket descriptor */
+ VALUE socket_io;
+ /* Proc object that receives notices as PG::Result objects */
+ VALUE notice_receiver;
+ /* Proc object that receives notices as String objects */
+ VALUE notice_processor;
+ /* Kind of PG::TypeMap object for casting query params */
+ VALUE type_map_for_queries;
+ /* Kind of PG::TypeMap object for casting result values */
+ VALUE type_map_for_results;
+ /* IO object internally used for the trace stream */
+ VALUE trace_stream;
+ /* Cached Encoding object */
+ VALUE external_encoding;
+ /* Kind of PG::Coder object for casting ruby values to COPY rows */
+ VALUE encoder_for_put_copy_data;
+ /* Kind of PG::Coder object for casting COPY rows to ruby values */
+ VALUE decoder_for_get_copy_data;
+
+} t_pg_connection;
+
+typedef struct pg_coder t_pg_coder;
+typedef struct pg_typemap t_typemap;
+
+/* The data behind each PG::Result object */
+typedef struct {
+ PGresult *pgresult;
+
+ /* The connection object used to build this result */
+ VALUE connection;
+
+ /* The TypeMap used to type cast result values */
+ VALUE typemap;
+
+ /* Pointer to the typemap object data. This is assumed to be
+ * always valid.
+ */
+ t_typemap *p_typemap;
+
+ /* 0 = PGresult is cleared by PG::Result#clear or by the GC
+ * 1 = PGresult is cleared internally by libpq
+ */
+ int autoclear;
+} t_pg_result;
+
+
+typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *);
+typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
+typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
+typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
+typedef int (* t_pg_fit_to_copy_get)(VALUE);
+typedef VALUE (* t_pg_typecast_result)(VALUE, int, int);
+typedef t_pg_coder *(* t_pg_typecast_query_param)(VALUE, VALUE, int);
+typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
+
+struct pg_coder {
+ t_pg_coder_enc_func enc_func;
+ t_pg_coder_dec_func dec_func;
+ VALUE coder_obj;
+ Oid oid;
+ int format;
+};
+
+typedef struct {
+ t_pg_coder comp;
+ t_pg_coder *elem;
+ int needs_quotation;
+ char delimiter;
+} t_pg_composite_coder;
+
+struct pg_typemap {
+ t_pg_fit_to_result fit_to_result;
+ t_pg_fit_to_query fit_to_query;
+ t_pg_fit_to_copy_get fit_to_copy_get;
+ t_pg_typecast_result typecast_result_value;
+ t_pg_typecast_query_param typecast_query_param;
+ t_pg_typecast_copy_get typecast_copy_get;
+};
+
+typedef struct {
+ t_typemap typemap;
+ int nfields;
+ struct pg_tmbc_converter {
+ t_pg_coder *cconv;
+ } convs[0];
+} t_tmbc;
+
+
#include "gvl_wrappers.h"
/***************************************************************************
* Globals
**************************************************************************/
@@ -114,11 +229,27 @@
extern VALUE rb_eConnectionBad;
extern VALUE rb_mPGconstants;
extern VALUE rb_cPGconn;
extern VALUE rb_cPGresult;
extern VALUE rb_hErrors;
+extern VALUE rb_cTypeMap;
+extern VALUE rb_cTypeMapAllStrings;
+extern VALUE rb_cPG_Coder;
+extern VALUE rb_cPG_SimpleEncoder;
+extern VALUE rb_cPG_SimpleDecoder;
+extern VALUE rb_cPG_CompositeEncoder;
+extern VALUE rb_cPG_CompositeDecoder;
+extern VALUE rb_cPG_CopyCoder;
+extern VALUE rb_cPG_CopyEncoder;
+extern VALUE rb_cPG_CopyDecoder;
+extern VALUE rb_mPG_TextEncoder;
+extern VALUE rb_mPG_TextDecoder;
+extern VALUE rb_mPG_BinaryEncoder;
+extern VALUE rb_mPG_BinaryDecoder;
+extern const t_typemap pg_tmbc_default_typemap;
+extern VALUE pg_default_typemap;
/***************************************************************************
* MACROS
**************************************************************************/
@@ -132,22 +263,79 @@
void Init_pg_ext _(( void ));
void init_pg_connection _(( void ));
void init_pg_result _(( void ));
void init_pg_errors _(( void ));
-VALUE lookup_error_class _(( const char *sqlstate ));
+void init_pg_type_map _(( void ));
+void init_pg_type_map_all_strings _(( void ));
+void init_pg_type_map_by_column _(( void ));
+void init_pg_type_map_by_mri_type _(( void ));
+void init_pg_type_map_by_oid _(( void ));
+void init_pg_coder _(( void ));
+void init_pg_copycoder _(( void ));
+void init_pg_text_encoder _(( void ));
+void init_pg_text_decoder _(( void ));
+void init_pg_binary_encoder _(( void ));
+void init_pg_binary_decoder _(( void ));
+VALUE lookup_error_class _(( const char * ));
+VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
+VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
+int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *));
+t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
+t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
+void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
+VALUE pg_obj_to_i _(( VALUE ));
+VALUE pg_tmbc_allocate _(( void ));
+void pg_coder_init_encoder _(( VALUE ));
+void pg_coder_init_decoder _(( VALUE ));
+char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
-PGconn *pg_get_pgconn _(( VALUE ));
+#define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
+ do { \
+ if( (curr_ptr) + (expand_len) >= (end_ptr) ) \
+ (curr_ptr) = pg_rb_str_ensure_capa( (str), (expand_len), (curr_ptr), &(end_ptr) ); \
+ } while(0);
+#define PG_RB_STR_NEW( str, curr_ptr, end_ptr ) ( \
+ (str) = rb_str_new( NULL, 0 ), \
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
+ )
+
+#define PG_RB_TAINTED_STR_NEW( str, curr_ptr, end_ptr ) ( \
+ (str) = rb_tainted_str_new( NULL, 0 ), \
+ (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
+ )
+
+VALUE pg_typemap_fit_to_result _(( VALUE, VALUE ));
+VALUE pg_typemap_fit_to_query _(( VALUE, VALUE ));
+int pg_typemap_fit_to_copy_get _(( VALUE ));
+VALUE pg_typemap_result_value _(( VALUE, int, int ));
+t_pg_coder *pg_typemap_typecast_query_param _(( VALUE, VALUE, int ));
+VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
+
+PGconn *pg_get_pgconn _(( VALUE ));
+t_pg_connection *pg_get_connection _(( VALUE ));
+
VALUE pg_new_result _(( PGresult *, VALUE ));
+VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
+PGresult* pgresult_get _(( VALUE ));
VALUE pg_result_check _(( VALUE ));
VALUE pg_result_clear _(( VALUE ));
+/*
+ * Fetch the data pointer for the result object
+ */
+static inline t_pg_result *
+pgresult_get_this( VALUE self )
+{
+ return DATA_PTR(self);
+}
+
+
#ifdef M17N_SUPPORTED
rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
-int pg_enc_get_index _(( VALUE ));
rb_encoding *pg_conn_enc_get _(( PGconn * ));
#endif /* M17N_SUPPORTED */
void notice_receiver_proxy(void *arg, const PGresult *result);
void notice_processor_proxy(void *arg, const char *message);