pg 0.15.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -3
- data/ChangeLog +361 -59
- data/History.rdoc +31 -4
- data/Manifest.txt +4 -0
- data/Rakefile +30 -10
- data/ext/errorcodes.def +931 -0
- data/ext/errorcodes.rb +45 -0
- data/ext/errorcodes.txt +463 -0
- data/ext/extconf.rb +11 -5
- data/ext/gvl_wrappers.c +6 -0
- data/ext/gvl_wrappers.h +47 -21
- data/ext/pg.c +30 -10
- data/ext/pg.h +30 -0
- data/ext/pg_connection.c +105 -45
- data/ext/pg_errors.c +89 -0
- data/ext/pg_result.c +49 -68
- data/lib/pg.rb +2 -2
- data/spec/lib/helpers.rb +11 -2
- data/spec/pg/connection_spec.rb +113 -8
- data/spec/pg/result_spec.rb +69 -2
- data/spec/pg_spec.rb +13 -0
- metadata +11 -5
- metadata.gz.sig +0 -0
    
        data/ext/extconf.rb
    CHANGED
    
    | @@ -27,17 +27,22 @@ if ENV['CROSS_COMPILING'] | |
| 27 27 | 
             
            	have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
         | 
| 28 28 | 
             
            end
         | 
| 29 29 |  | 
| 30 | 
            -
            dir_config 'pg'
         | 
| 31 | 
            -
             | 
| 32 30 | 
             
            if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
         | 
| 33 31 | 
             
            	$stderr.puts "Using config values from %s" % [ pgconfig ]
         | 
| 34 | 
            -
            	 | 
| 35 | 
            -
             | 
| 32 | 
            +
            	incdir = `"#{pgconfig}" --includedir`.chomp
         | 
| 36 33 | 
             
            	libdir = `"#{pgconfig}" --libdir`.chomp
         | 
| 37 | 
            -
            	 | 
| 34 | 
            +
            	dir_config 'pg', incdir, libdir
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            	# Try to use runtime path linker option, even if RbConfig doesn't know about it.
         | 
| 37 | 
            +
            	# The rpath option is usually set implicit by dir_config(), but so far not
         | 
| 38 | 
            +
            	# on MacOS-X.
         | 
| 39 | 
            +
            	if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
         | 
| 40 | 
            +
            		$LDFLAGS << " -Wl,-rpath,#{libdir}"
         | 
| 41 | 
            +
            	end
         | 
| 38 42 | 
             
            else
         | 
| 39 43 | 
             
            	$stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
         | 
| 40 44 | 
             
            		" --with-pg-config=/path/to/pg_config"
         | 
| 45 | 
            +
            	dir_config 'pg'
         | 
| 41 46 | 
             
            end
         | 
| 42 47 |  | 
| 43 48 | 
             
            find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
         | 
| @@ -78,6 +83,7 @@ have_func 'rb_w32_wrap_io_handle' | |
| 78 83 |  | 
| 79 84 | 
             
            have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
         | 
| 80 85 | 
             
            have_const 'PGRES_SINGLE_TUPLE', 'libpq-fe.h'
         | 
| 86 | 
            +
            have_const 'PG_DIAG_TABLE_NAME', 'libpq-fe.h'
         | 
| 81 87 |  | 
| 82 88 | 
             
            $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
         | 
| 83 89 | 
             
            	have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
         | 
    
        data/ext/gvl_wrappers.c
    CHANGED
    
    | @@ -11,3 +11,9 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB ); | |
| 11 11 | 
             
            FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
         | 
| 12 12 | 
             
            FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
         | 
| 13 13 | 
             
            FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            void ubf_cancel_running_command(void *c)
         | 
| 16 | 
            +
            {
         | 
| 17 | 
            +
            	PGconn *conn = (PGconn*) c;
         | 
| 18 | 
            +
            	PQrequestCancel(conn);
         | 
| 19 | 
            +
            }
         | 
    
        data/ext/gvl_wrappers.h
    CHANGED
    
    | @@ -24,6 +24,8 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 24 24 | 
             
            				 rb_unblock_function_t *ubf, void *data2);
         | 
| 25 25 | 
             
            #endif
         | 
| 26 26 |  | 
| 27 | 
            +
            void ubf_cancel_running_command(void *c);
         | 
| 28 | 
            +
             | 
| 27 29 | 
             
            #define DEFINE_PARAM_LIST1(type, name) \
         | 
| 28 30 | 
             
            	name,
         | 
| 29 31 |  | 
| @@ -36,7 +38,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 36 38 | 
             
            #define DEFINE_PARAM_DECL(type, name) \
         | 
| 37 39 | 
             
            	type name;
         | 
| 38 40 |  | 
| 39 | 
            -
            #define DEFINE_GVL_WRAPPER_STRUCT(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 41 | 
            +
            #define DEFINE_GVL_WRAPPER_STRUCT(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 40 42 | 
             
            	struct gvl_wrapper_##name##_params { \
         | 
| 41 43 | 
             
            		struct { \
         | 
| 42 44 | 
             
            			FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_DECL) \
         | 
| @@ -45,7 +47,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 45 47 | 
             
            		when_non_void( rettype retval; ) \
         | 
| 46 48 | 
             
            	};
         | 
| 47 49 |  | 
| 48 | 
            -
            #define DEFINE_GVL_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 50 | 
            +
            #define DEFINE_GVL_SKELETON(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 49 51 | 
             
            	static void * gvl_##name##_skeleton( void *data ){ \
         | 
| 50 52 | 
             
            		struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
         | 
| 51 53 | 
             
            		when_non_void( p->retval = ) \
         | 
| @@ -54,25 +56,25 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 54 56 | 
             
            	}
         | 
| 55 57 |  | 
| 56 58 | 
             
            #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
         | 
| 57 | 
            -
            	#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 59 | 
            +
            	#define DEFINE_GVL_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 58 60 | 
             
            		rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
         | 
| 59 61 | 
             
            			struct gvl_wrapper_##name##_params params = { \
         | 
| 60 62 | 
             
            				{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
         | 
| 61 63 | 
             
            			}; \
         | 
| 62 | 
            -
            			rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms,  | 
| 64 | 
            +
            			rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms, cancel_params); \
         | 
| 63 65 | 
             
            			when_non_void( return params.retval; ) \
         | 
| 64 66 | 
             
            		}
         | 
| 65 67 | 
             
            #else
         | 
| 66 | 
            -
            	#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 68 | 
            +
            	#define DEFINE_GVL_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 67 69 | 
             
            		rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
         | 
| 68 70 | 
             
            			return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
         | 
| 69 71 | 
             
            		}
         | 
| 70 72 | 
             
            #endif
         | 
| 71 73 |  | 
| 72 | 
            -
            #define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 74 | 
            +
            #define DEFINE_GVL_STUB_DECL(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 73 75 | 
             
            	rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
         | 
| 74 76 |  | 
| 75 | 
            -
            #define DEFINE_GVLCB_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 77 | 
            +
            #define DEFINE_GVLCB_SKELETON(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 76 78 | 
             
            	static void * gvl_##name##_skeleton( void *data ){ \
         | 
| 77 79 | 
             
            		struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
         | 
| 78 80 | 
             
            		when_non_void( p->retval = ) \
         | 
| @@ -81,7 +83,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 81 83 | 
             
            	}
         | 
| 82 84 |  | 
| 83 85 | 
             
            #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
         | 
| 84 | 
            -
            	#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 86 | 
            +
            	#define DEFINE_GVLCB_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 85 87 | 
             
            		rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
         | 
| 86 88 | 
             
            			struct gvl_wrapper_##name##_params params = { \
         | 
| 87 89 | 
             
            				{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
         | 
| @@ -90,7 +92,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 90 92 | 
             
            			when_non_void( return params.retval; ) \
         | 
| 91 93 | 
             
            		}
         | 
| 92 94 | 
             
            #else
         | 
| 93 | 
            -
            	#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 95 | 
            +
            	#define DEFINE_GVLCB_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
         | 
| 94 96 | 
             
            		rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
         | 
| 95 97 | 
             
            			return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
         | 
| 96 98 | 
             
            		}
         | 
| @@ -99,11 +101,26 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 99 101 | 
             
            #define GVL_TYPE_VOID(string)
         | 
| 100 102 | 
             
            #define GVL_TYPE_NONVOID(string) string
         | 
| 101 103 |  | 
| 104 | 
            +
            #define GVL_CANCELABLE ubf_cancel_running_command, conn
         | 
| 105 | 
            +
            #define GVL_NONCANCELABLE RUBY_UBF_IO, 0
         | 
| 106 | 
            +
             | 
| 102 107 |  | 
| 103 108 | 
             
            /*
         | 
| 104 109 | 
             
             * Definitions of blocking functions and their parameters
         | 
| 105 110 | 
             
             */
         | 
| 106 111 |  | 
| 112 | 
            +
            #define FOR_EACH_PARAM_OF_PQconnectdb(param)
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            #define FOR_EACH_PARAM_OF_PQconnectStart(param)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            #define FOR_EACH_PARAM_OF_PQconnectPoll(param)
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            #define FOR_EACH_PARAM_OF_PQreset(param)
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            #define FOR_EACH_PARAM_OF_PQresetStart(param)
         | 
| 121 | 
            +
             | 
| 122 | 
            +
            #define FOR_EACH_PARAM_OF_PQresetPoll(param)
         | 
| 123 | 
            +
             | 
| 107 124 | 
             
            #define FOR_EACH_PARAM_OF_PQexec(param) \
         | 
| 108 125 | 
             
            	param(PGconn *, conn)
         | 
| 109 126 |  | 
| @@ -149,18 +166,27 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, | |
| 149 166 | 
             
            	param(PGconn *, conn) \
         | 
| 150 167 | 
             
            	param(char **, buffer)
         | 
| 151 168 |  | 
| 169 | 
            +
            #define FOR_EACH_PARAM_OF_PQnotifies(param)
         | 
| 170 | 
            +
             | 
| 152 171 | 
             
            /* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
         | 
| 153 172 | 
             
            #define FOR_EACH_BLOCKING_FUNCTION(function) \
         | 
| 154 | 
            -
            	function( | 
| 155 | 
            -
            	function( | 
| 156 | 
            -
            	function( | 
| 157 | 
            -
            	function( | 
| 158 | 
            -
            	function( | 
| 159 | 
            -
            	function( | 
| 160 | 
            -
            	function( | 
| 161 | 
            -
            	function( | 
| 162 | 
            -
            	function( | 
| 163 | 
            -
            	function( | 
| 173 | 
            +
            	function(PQconnectdb, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
         | 
| 174 | 
            +
            	function(PQconnectStart, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
         | 
| 175 | 
            +
            	function(PQconnectPoll, GVL_CANCELABLE, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
         | 
| 176 | 
            +
            	function(PQreset, GVL_CANCELABLE, GVL_TYPE_VOID, void, PGconn *, conn) \
         | 
| 177 | 
            +
            	function(PQresetStart, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, PGconn *, conn) \
         | 
| 178 | 
            +
            	function(PQresetPoll, GVL_CANCELABLE, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
         | 
| 179 | 
            +
            	function(PQexec, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
         | 
| 180 | 
            +
            	function(PQexecParams, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
         | 
| 181 | 
            +
            	function(PQexecPrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
         | 
| 182 | 
            +
            	function(PQprepare, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
         | 
| 183 | 
            +
            	function(PQdescribePrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
         | 
| 184 | 
            +
            	function(PQdescribePortal, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
         | 
| 185 | 
            +
            	function(PQgetResult, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
         | 
| 186 | 
            +
            	function(PQputCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, nbytes) \
         | 
| 187 | 
            +
            	function(PQputCopyEnd, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, errormsg) \
         | 
| 188 | 
            +
            	function(PQgetCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, async) \
         | 
| 189 | 
            +
            	function(PQnotifies, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGnotify *, PGconn *, conn);
         | 
| 164 190 |  | 
| 165 191 | 
             
            FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
         | 
| 166 192 |  | 
| @@ -177,8 +203,8 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL ); | |
| 177 203 |  | 
| 178 204 | 
             
            /* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
         | 
| 179 205 | 
             
            #define FOR_EACH_CALLBACK_FUNCTION(function) \
         | 
| 180 | 
            -
            	function(notice_processor_proxy | 
| 181 | 
            -
            	function(notice_receiver_proxy | 
| 206 | 
            +
            	function(notice_processor_proxy,, GVL_TYPE_VOID, void, const char *, message) \
         | 
| 207 | 
            +
            	function(notice_receiver_proxy,, GVL_TYPE_VOID, void, const PGresult *, result) \
         | 
| 182 208 |  | 
| 183 209 | 
             
            FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_STUB_DECL );
         | 
| 184 210 |  | 
    
        data/ext/pg.c
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            /*
         | 
| 2 2 | 
             
             * pg.c - Toplevel extension
         | 
| 3 | 
            -
             * $Id: pg.c,v  | 
| 3 | 
            +
             * $Id: pg.c,v 74aa9514a381 2013/05/18 17:29:19 lars $
         | 
| 4 4 | 
             
             *
         | 
| 5 5 | 
             
             * Author/s:
         | 
| 6 6 | 
             
             *
         | 
| @@ -48,7 +48,6 @@ | |
| 48 48 | 
             
            #include "pg.h"
         | 
| 49 49 |  | 
| 50 50 | 
             
            VALUE rb_mPG;
         | 
| 51 | 
            -
            VALUE rb_ePGerror;
         | 
| 52 51 | 
             
            VALUE rb_mPGconstants;
         | 
| 53 52 |  | 
| 54 53 |  | 
| @@ -300,7 +299,6 @@ void | |
| 300 299 | 
             
            Init_pg_ext()
         | 
| 301 300 | 
             
            {
         | 
| 302 301 | 
             
            	rb_mPG = rb_define_module( "PG" );
         | 
| 303 | 
            -
            	rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
         | 
| 304 302 | 
             
            	rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
         | 
| 305 303 |  | 
| 306 304 | 
             
            	/*************************
         | 
| @@ -313,13 +311,6 @@ Init_pg_ext() | |
| 313 311 | 
             
            	SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
         | 
| 314 312 | 
             
            	SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
         | 
| 315 313 |  | 
| 316 | 
            -
            	/*************************
         | 
| 317 | 
            -
            	 *  PG::Error
         | 
| 318 | 
            -
            	 *************************/
         | 
| 319 | 
            -
            	rb_define_alias( rb_ePGerror, "error", "message" );
         | 
| 320 | 
            -
            	rb_define_attr( rb_ePGerror, "connection", 1, 0 );
         | 
| 321 | 
            -
            	rb_define_attr( rb_ePGerror, "result", 1, 0 );
         | 
| 322 | 
            -
             | 
| 323 314 | 
             
            	/******     PG::Connection CLASS CONSTANTS: Connection Status     ******/
         | 
| 324 315 |  | 
| 325 316 | 
             
            	/* Connection succeeded */
         | 
| @@ -506,6 +497,34 @@ Init_pg_ext() | |
| 506 497 | 
             
            	 * function reporting the error. */
         | 
| 507 498 | 
             
            	rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FUNCTION", INT2FIX(PG_DIAG_SOURCE_FUNCTION));
         | 
| 508 499 |  | 
| 500 | 
            +
            #ifdef HAVE_CONST_PG_DIAG_TABLE_NAME
         | 
| 501 | 
            +
            	/* #result_error_field argument constant: If the error was associated with a
         | 
| 502 | 
            +
            	 * specific database object, the name of the schema containing that object, if any. */
         | 
| 503 | 
            +
            	rb_define_const(rb_mPGconstants, "PG_DIAG_SCHEMA_NAME", INT2FIX(PG_DIAG_SCHEMA_NAME));
         | 
| 504 | 
            +
             | 
| 505 | 
            +
            	/* #result_error_field argument constant: If the error was associated with a
         | 
| 506 | 
            +
            	 *specific table, the name of the table. (When this field is present, the schema name
         | 
| 507 | 
            +
            	 * field provides the name of the table's schema.) */
         | 
| 508 | 
            +
            	rb_define_const(rb_mPGconstants, "PG_DIAG_TABLE_NAME", INT2FIX(PG_DIAG_TABLE_NAME));
         | 
| 509 | 
            +
             | 
| 510 | 
            +
            	/* #result_error_field argument constant: If the error was associated with a
         | 
| 511 | 
            +
            	 * specific table column, the name of the column. (When this field is present, the
         | 
| 512 | 
            +
            	 * schema and table name fields identify the table.) */
         | 
| 513 | 
            +
            	rb_define_const(rb_mPGconstants, "PG_DIAG_COLUMN_NAME", INT2FIX(PG_DIAG_COLUMN_NAME));
         | 
| 514 | 
            +
             | 
| 515 | 
            +
            	/* #result_error_field argument constant: If the error was associated with a
         | 
| 516 | 
            +
            	 * specific datatype, the name of the datatype. (When this field is present, the
         | 
| 517 | 
            +
            	 * schema name field provides the name of the datatype's schema.) */
         | 
| 518 | 
            +
            	rb_define_const(rb_mPGconstants, "PG_DIAG_DATATYPE_NAME", INT2FIX(PG_DIAG_DATATYPE_NAME));
         | 
| 519 | 
            +
             | 
| 520 | 
            +
            	/* #result_error_field argument constant: If the error was associated with a
         | 
| 521 | 
            +
            	 * specific constraint, the name of the constraint. The table or domain that the
         | 
| 522 | 
            +
            	 * constraint belongs to is reported using the fields listed above. (For this
         | 
| 523 | 
            +
            	 * purpose, indexes are treated as constraints, even if they weren't created with
         | 
| 524 | 
            +
            	 * constraint syntax.) */
         | 
| 525 | 
            +
            	rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
         | 
| 526 | 
            +
            #endif
         | 
| 527 | 
            +
             | 
| 509 528 | 
             
            	/* Invalid OID constant */
         | 
| 510 529 | 
             
            	rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
         | 
| 511 530 | 
             
            	rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
         | 
| @@ -521,5 +540,6 @@ Init_pg_ext() | |
| 521 540 | 
             
            	/* Initialize the main extension classes */
         | 
| 522 541 | 
             
            	init_pg_connection();
         | 
| 523 542 | 
             
            	init_pg_result();
         | 
| 543 | 
            +
            	init_pg_errors();
         | 
| 524 544 | 
             
            }
         | 
| 525 545 |  | 
    
        data/ext/pg.h
    CHANGED
    
    | @@ -66,6 +66,30 @@ | |
| 66 66 | 
             
            #	include "ruby/io.h"
         | 
| 67 67 | 
             
            #endif
         | 
| 68 68 |  | 
| 69 | 
            +
            #ifndef timeradd
         | 
| 70 | 
            +
            #define timeradd(a, b, result) \
         | 
| 71 | 
            +
            	do { \
         | 
| 72 | 
            +
            		(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
         | 
| 73 | 
            +
            		(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
         | 
| 74 | 
            +
            		if ((result)->tv_usec >= 1000000L) { \
         | 
| 75 | 
            +
            			++(result)->tv_sec; \
         | 
| 76 | 
            +
            			(result)->tv_usec -= 1000000L; \
         | 
| 77 | 
            +
            		} \
         | 
| 78 | 
            +
            	} while (0)
         | 
| 79 | 
            +
            #endif
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            #ifndef timersub
         | 
| 82 | 
            +
            #define timersub(a, b, result) \
         | 
| 83 | 
            +
            	do { \
         | 
| 84 | 
            +
            		(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
         | 
| 85 | 
            +
            		(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
         | 
| 86 | 
            +
            		if ((result)->tv_usec < 0) { \
         | 
| 87 | 
            +
            			--(result)->tv_sec; \
         | 
| 88 | 
            +
            			(result)->tv_usec += 1000000L; \
         | 
| 89 | 
            +
            		} \
         | 
| 90 | 
            +
            	} while (0)
         | 
| 91 | 
            +
            #endif
         | 
| 92 | 
            +
             | 
| 69 93 | 
             
            /* PostgreSQL headers */
         | 
| 70 94 | 
             
            #include "libpq-fe.h"
         | 
| 71 95 | 
             
            #include "libpq/libpq-fs.h"              /* large-object interface */
         | 
| @@ -85,9 +109,13 @@ typedef long suseconds_t; | |
| 85 109 |  | 
| 86 110 | 
             
            extern VALUE rb_mPG;
         | 
| 87 111 | 
             
            extern VALUE rb_ePGerror;
         | 
| 112 | 
            +
            extern VALUE rb_eServerError;
         | 
| 113 | 
            +
            extern VALUE rb_eUnableToSend;
         | 
| 114 | 
            +
            extern VALUE rb_eConnectionBad;
         | 
| 88 115 | 
             
            extern VALUE rb_mPGconstants;
         | 
| 89 116 | 
             
            extern VALUE rb_cPGconn;
         | 
| 90 117 | 
             
            extern VALUE rb_cPGresult;
         | 
| 118 | 
            +
            extern VALUE rb_hErrors;
         | 
| 91 119 |  | 
| 92 120 |  | 
| 93 121 | 
             
            /***************************************************************************
         | 
| @@ -105,6 +133,8 @@ void Init_pg_ext                                       _(( void )); | |
| 105 133 |  | 
| 106 134 | 
             
            void init_pg_connection                                _(( void ));
         | 
| 107 135 | 
             
            void init_pg_result                                    _(( void ));
         | 
| 136 | 
            +
            void init_pg_errors                                    _(( void ));
         | 
| 137 | 
            +
            VALUE lookup_error_class                               _(( const char *sqlstate ));
         | 
| 108 138 |  | 
| 109 139 | 
             
            PGconn *pg_get_pgconn	                               _(( VALUE ));
         | 
| 110 140 |  | 
    
        data/ext/pg_connection.c
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            /*
         | 
| 2 2 | 
             
             * pg_connection.c - PG::Connection class extension
         | 
| 3 | 
            -
             * $Id: pg_connection.c,v  | 
| 3 | 
            +
             * $Id: pg_connection.c,v 854b22230eba 2013/07/18 13:33:09 kanis $
         | 
| 4 4 | 
             
             *
         | 
| 5 5 | 
             
             */
         | 
| 6 6 |  | 
| @@ -40,7 +40,7 @@ pg_get_pgconn( VALUE self ) | |
| 40 40 | 
             
            	PGconn *conn = pgconn_check( self );
         | 
| 41 41 |  | 
| 42 42 | 
             
            	if ( !conn )
         | 
| 43 | 
            -
            		rb_raise(  | 
| 43 | 
            +
            		rb_raise( rb_eConnectionBad, "connection is closed" );
         | 
| 44 44 |  | 
| 45 45 | 
             
            	return conn;
         | 
| 46 46 | 
             
            }
         | 
| @@ -58,7 +58,7 @@ pgconn_close_socket_io( VALUE self ) | |
| 58 58 | 
             
            #if defined(_WIN32) && defined(HAVE_RB_W32_WRAP_IO_HANDLE)
         | 
| 59 59 | 
             
            		int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
         | 
| 60 60 | 
             
            		if( rb_w32_unwrap_io_handle(ruby_sd) ){
         | 
| 61 | 
            -
            			rb_raise( | 
| 61 | 
            +
            			rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
         | 
| 62 62 | 
             
            		}
         | 
| 63 63 | 
             
            #endif
         | 
| 64 64 | 
             
            		rb_funcall( socket_io, rb_intern("close"), 0 );
         | 
| @@ -113,7 +113,11 @@ pgconn_gc_free( PGconn *conn ) | |
| 113 113 | 
             
            static VALUE
         | 
| 114 114 | 
             
            pgconn_s_allocate( VALUE klass )
         | 
| 115 115 | 
             
            {
         | 
| 116 | 
            -
            	 | 
| 116 | 
            +
            	VALUE self = Data_Wrap_Struct( klass, NULL, pgconn_gc_free, NULL );
         | 
| 117 | 
            +
            	rb_iv_set( self, "@socket_io", Qnil );
         | 
| 118 | 
            +
            	rb_iv_set( self, "@notice_receiver", Qnil);
         | 
| 119 | 
            +
            	rb_iv_set( self, "@notice_processor", Qnil);
         | 
| 120 | 
            +
            	return self;
         | 
| 117 121 | 
             
            }
         | 
| 118 122 |  | 
| 119 123 |  | 
| @@ -182,16 +186,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self) | |
| 182 186 | 
             
            	VALUE error;
         | 
| 183 187 |  | 
| 184 188 | 
             
            	conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
         | 
| 185 | 
            -
            	conn =  | 
| 189 | 
            +
            	conn = gvl_PQconnectdb(StringValuePtr(conninfo));
         | 
| 186 190 |  | 
| 187 191 | 
             
            	if(conn == NULL)
         | 
| 188 | 
            -
            		rb_raise(rb_ePGerror, " | 
| 192 | 
            +
            		rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
         | 
| 189 193 |  | 
| 190 194 | 
             
            	Check_Type(self, T_DATA);
         | 
| 191 195 | 
             
            	DATA_PTR(self) = conn;
         | 
| 192 196 |  | 
| 193 197 | 
             
            	if (PQstatus(conn) == CONNECTION_BAD) {
         | 
| 194 | 
            -
            		error = rb_exc_new2( | 
| 198 | 
            +
            		error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
         | 
| 195 199 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 196 200 | 
             
            		rb_exc_raise(error);
         | 
| 197 201 | 
             
            	}
         | 
| @@ -236,7 +240,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass ) | |
| 236 240 | 
             
            	 */
         | 
| 237 241 | 
             
            	rb_conn  = pgconn_s_allocate( klass );
         | 
| 238 242 | 
             
            	conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
         | 
| 239 | 
            -
            	conn     =  | 
| 243 | 
            +
            	conn     = gvl_PQconnectStart( StringValuePtr(conninfo) );
         | 
| 240 244 |  | 
| 241 245 | 
             
            	if( conn == NULL )
         | 
| 242 246 | 
             
            		rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
         | 
| @@ -245,7 +249,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass ) | |
| 245 249 | 
             
            	DATA_PTR(rb_conn) = conn;
         | 
| 246 250 |  | 
| 247 251 | 
             
            	if ( PQstatus(conn) == CONNECTION_BAD ) {
         | 
| 248 | 
            -
            		error = rb_exc_new2( | 
| 252 | 
            +
            		error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
         | 
| 249 253 | 
             
            		rb_iv_set(error, "@connection", rb_conn);
         | 
| 250 254 | 
             
            		rb_exc_raise(error);
         | 
| 251 255 | 
             
            	}
         | 
| @@ -415,7 +419,7 @@ static VALUE | |
| 415 419 | 
             
            pgconn_connect_poll(VALUE self)
         | 
| 416 420 | 
             
            {
         | 
| 417 421 | 
             
            	PostgresPollingStatusType status;
         | 
| 418 | 
            -
            	status =  | 
| 422 | 
            +
            	status = gvl_PQconnectPoll(pg_get_pgconn(self));
         | 
| 419 423 | 
             
            	return INT2FIX((int)status);
         | 
| 420 424 | 
             
            }
         | 
| 421 425 |  | 
| @@ -460,7 +464,7 @@ static VALUE | |
| 460 464 | 
             
            pgconn_reset( VALUE self )
         | 
| 461 465 | 
             
            {
         | 
| 462 466 | 
             
            	pgconn_close_socket_io( self );
         | 
| 463 | 
            -
            	 | 
| 467 | 
            +
            	gvl_PQreset( pg_get_pgconn(self) );
         | 
| 464 468 | 
             
            	return self;
         | 
| 465 469 | 
             
            }
         | 
| 466 470 |  | 
| @@ -478,8 +482,8 @@ static VALUE | |
| 478 482 | 
             
            pgconn_reset_start(VALUE self)
         | 
| 479 483 | 
             
            {
         | 
| 480 484 | 
             
            	pgconn_close_socket_io( self );
         | 
| 481 | 
            -
            	if( | 
| 482 | 
            -
            		rb_raise( | 
| 485 | 
            +
            	if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
         | 
| 486 | 
            +
            		rb_raise(rb_eUnableToSend, "reset has failed");
         | 
| 483 487 | 
             
            	return Qnil;
         | 
| 484 488 | 
             
            }
         | 
| 485 489 |  | 
| @@ -495,7 +499,7 @@ static VALUE | |
| 495 499 | 
             
            pgconn_reset_poll(VALUE self)
         | 
| 496 500 | 
             
            {
         | 
| 497 501 | 
             
            	PostgresPollingStatusType status;
         | 
| 498 | 
            -
            	status =  | 
| 502 | 
            +
            	status = gvl_PQresetPoll(pg_get_pgconn(self));
         | 
| 499 503 | 
             
            	return INT2FIX((int)status);
         | 
| 500 504 | 
             
            }
         | 
| 501 505 |  | 
| @@ -718,7 +722,7 @@ pgconn_socket(VALUE self) | |
| 718 722 | 
             
            {
         | 
| 719 723 | 
             
            	int sd;
         | 
| 720 724 | 
             
            	if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
         | 
| 721 | 
            -
            		rb_raise( | 
| 725 | 
            +
            		rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
         | 
| 722 726 | 
             
            	return INT2NUM(sd);
         | 
| 723 727 | 
             
            }
         | 
| 724 728 |  | 
| @@ -749,7 +753,7 @@ pgconn_socket_io(VALUE self) | |
| 749 753 |  | 
| 750 754 | 
             
            	if ( !RTEST(socket_io) ) {
         | 
| 751 755 | 
             
            		if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
         | 
| 752 | 
            -
            			rb_raise( | 
| 756 | 
            +
            			rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
         | 
| 753 757 |  | 
| 754 758 | 
             
            		#ifdef _WIN32
         | 
| 755 759 | 
             
            			ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
         | 
| @@ -1448,6 +1452,10 @@ pgconn_escape_literal(VALUE self, VALUE string) | |
| 1448 1452 | 
             
            	PQfreemem(escaped);
         | 
| 1449 1453 | 
             
            	OBJ_INFECT(result, string);
         | 
| 1450 1454 |  | 
| 1455 | 
            +
            #ifdef M17N_SUPPORTED
         | 
| 1456 | 
            +
            	rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
         | 
| 1457 | 
            +
            #endif
         | 
| 1458 | 
            +
             | 
| 1451 1459 | 
             
            	return result;
         | 
| 1452 1460 | 
             
            }
         | 
| 1453 1461 | 
             
            #endif
         | 
| @@ -1458,6 +1466,9 @@ pgconn_escape_literal(VALUE self, VALUE string) | |
| 1458 1466 | 
             
             *    conn.escape_identifier( str ) -> String
         | 
| 1459 1467 | 
             
             *
         | 
| 1460 1468 | 
             
             * Escape an arbitrary String +str+ as an identifier.
         | 
| 1469 | 
            +
             *
         | 
| 1470 | 
            +
             * This method does the same as #quote_ident, but uses libpq to
         | 
| 1471 | 
            +
             * process the string.
         | 
| 1461 1472 | 
             
             */
         | 
| 1462 1473 | 
             
            static VALUE
         | 
| 1463 1474 | 
             
            pgconn_escape_identifier(VALUE self, VALUE string)
         | 
| @@ -1481,6 +1492,10 @@ pgconn_escape_identifier(VALUE self, VALUE string) | |
| 1481 1492 | 
             
            	PQfreemem(escaped);
         | 
| 1482 1493 | 
             
            	OBJ_INFECT(result, string);
         | 
| 1483 1494 |  | 
| 1495 | 
            +
            #ifdef M17N_SUPPORTED
         | 
| 1496 | 
            +
            	rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
         | 
| 1497 | 
            +
            #endif
         | 
| 1498 | 
            +
             | 
| 1484 1499 | 
             
            	return result;
         | 
| 1485 1500 | 
             
            }
         | 
| 1486 1501 | 
             
            #endif
         | 
| @@ -1596,7 +1611,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self) | |
| 1596 1611 | 
             
            	/* If called with no parameters, use PQsendQuery */
         | 
| 1597 1612 | 
             
            	if(NIL_P(params)) {
         | 
| 1598 1613 | 
             
            		if(PQsendQuery(conn,StringValuePtr(command)) == 0) {
         | 
| 1599 | 
            -
            			error = rb_exc_new2( | 
| 1614 | 
            +
            			error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1600 1615 | 
             
            			rb_iv_set(error, "@connection", self);
         | 
| 1601 1616 | 
             
            			rb_exc_raise(error);
         | 
| 1602 1617 | 
             
            		}
         | 
| @@ -1679,7 +1694,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self) | |
| 1679 1694 | 
             
            	xfree(paramFormats);
         | 
| 1680 1695 |  | 
| 1681 1696 | 
             
            	if(result == 0) {
         | 
| 1682 | 
            -
            		error = rb_exc_new2( | 
| 1697 | 
            +
            		error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1683 1698 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1684 1699 | 
             
            		rb_exc_raise(error);
         | 
| 1685 1700 | 
             
            	}
         | 
| @@ -1741,7 +1756,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self) | |
| 1741 1756 | 
             
            	xfree(paramTypes);
         | 
| 1742 1757 |  | 
| 1743 1758 | 
             
            	if(result == 0) {
         | 
| 1744 | 
            -
            		error = rb_exc_new2( | 
| 1759 | 
            +
            		error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1745 1760 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1746 1761 | 
             
            		rb_exc_raise(error);
         | 
| 1747 1762 | 
             
            	}
         | 
| @@ -1864,7 +1879,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self) | |
| 1864 1879 | 
             
            	xfree(paramFormats);
         | 
| 1865 1880 |  | 
| 1866 1881 | 
             
            	if(result == 0) {
         | 
| 1867 | 
            -
            		error = rb_exc_new2( | 
| 1882 | 
            +
            		error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1868 1883 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1869 1884 | 
             
            		rb_exc_raise(error);
         | 
| 1870 1885 | 
             
            	}
         | 
| @@ -1885,7 +1900,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name) | |
| 1885 1900 | 
             
            	PGconn *conn = pg_get_pgconn(self);
         | 
| 1886 1901 | 
             
            	/* returns 0 on failure */
         | 
| 1887 1902 | 
             
            	if(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
         | 
| 1888 | 
            -
            		error = rb_exc_new2( | 
| 1903 | 
            +
            		error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1889 1904 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1890 1905 | 
             
            		rb_exc_raise(error);
         | 
| 1891 1906 | 
             
            	}
         | 
| @@ -1907,7 +1922,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal) | |
| 1907 1922 | 
             
            	PGconn *conn = pg_get_pgconn(self);
         | 
| 1908 1923 | 
             
            	/* returns 0 on failure */
         | 
| 1909 1924 | 
             
            	if(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
         | 
| 1910 | 
            -
            		error = rb_exc_new2( | 
| 1925 | 
            +
            		error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
         | 
| 1911 1926 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1912 1927 | 
             
            		rb_exc_raise(error);
         | 
| 1913 1928 | 
             
            	}
         | 
| @@ -1965,7 +1980,7 @@ pgconn_consume_input(self) | |
| 1965 1980 | 
             
            	PGconn *conn = pg_get_pgconn(self);
         | 
| 1966 1981 | 
             
            	/* returns 0 on error */
         | 
| 1967 1982 | 
             
            	if(PQconsumeInput(conn) == 0) {
         | 
| 1968 | 
            -
            		error = rb_exc_new2( | 
| 1983 | 
            +
            		error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
         | 
| 1969 1984 | 
             
            		rb_iv_set(error, "@connection", self);
         | 
| 1970 1985 | 
             
            		rb_exc_raise(error);
         | 
| 1971 1986 | 
             
            	}
         | 
| @@ -2122,7 +2137,7 @@ pgconn_notifies(VALUE self) | |
| 2122 2137 | 
             
            	sym_be_pid = ID2SYM(rb_intern("be_pid"));
         | 
| 2123 2138 | 
             
            	sym_extra = ID2SYM(rb_intern("extra"));
         | 
| 2124 2139 |  | 
| 2125 | 
            -
            	notification =  | 
| 2140 | 
            +
            	notification = gvl_PQnotifies(conn);
         | 
| 2126 2141 | 
             
            	if (notification == NULL) {
         | 
| 2127 2142 | 
             
            		return Qnil;
         | 
| 2128 2143 | 
             
            	}
         | 
| @@ -2199,32 +2214,46 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2199 2214 | 
             
            {
         | 
| 2200 2215 | 
             
            	int sd = PQsocket( conn );
         | 
| 2201 2216 | 
             
            	void *retval;
         | 
| 2217 | 
            +
            	struct timeval aborttime={0,0}, currtime, waittime;
         | 
| 2202 2218 | 
             
            	DWORD timeout_milisec = INFINITE;
         | 
| 2203 2219 | 
             
            	DWORD wait_ret;
         | 
| 2204 2220 | 
             
            	WSAEVENT hEvent;
         | 
| 2205 2221 |  | 
| 2206 2222 | 
             
            	if ( sd < 0 )
         | 
| 2207 | 
            -
            		 | 
| 2223 | 
            +
            		rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
         | 
| 2208 2224 |  | 
| 2209 2225 | 
             
            	hEvent = WSACreateEvent();
         | 
| 2210 2226 |  | 
| 2211 | 
            -
            	if ( ptimeout ) {
         | 
| 2212 | 
            -
            		timeout_milisec = (DWORD)( ptimeout->tv_sec * 1e3 + ptimeout->tv_usec / 1e3 );
         | 
| 2213 | 
            -
            	}
         | 
| 2214 | 
            -
             | 
| 2215 2227 | 
             
            	/* Check for connection errors (PQisBusy is true on connection errors) */
         | 
| 2216 2228 | 
             
            	if( PQconsumeInput(conn) == 0 ) {
         | 
| 2217 2229 | 
             
            		WSACloseEvent( hEvent );
         | 
| 2218 | 
            -
            		rb_raise(  | 
| 2230 | 
            +
            		rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
         | 
| 2231 | 
            +
            	}
         | 
| 2232 | 
            +
             | 
| 2233 | 
            +
            	if ( ptimeout ) {
         | 
| 2234 | 
            +
            		gettimeofday(&currtime, NULL);
         | 
| 2235 | 
            +
            		timeradd(&currtime, ptimeout, &aborttime);
         | 
| 2219 2236 | 
             
            	}
         | 
| 2220 2237 |  | 
| 2221 2238 | 
             
            	while ( !(retval=is_readable(conn)) ) {
         | 
| 2222 2239 | 
             
            		if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
         | 
| 2223 2240 | 
             
            			WSACloseEvent( hEvent );
         | 
| 2224 | 
            -
            			rb_raise(  | 
| 2241 | 
            +
            			rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
         | 
| 2225 2242 | 
             
            		}
         | 
| 2226 2243 |  | 
| 2227 | 
            -
            		 | 
| 2244 | 
            +
            		if ( ptimeout ) {
         | 
| 2245 | 
            +
            			gettimeofday(&currtime, NULL);
         | 
| 2246 | 
            +
            			timersub(&aborttime, &currtime, &waittime);
         | 
| 2247 | 
            +
            			timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
         | 
| 2248 | 
            +
            		}
         | 
| 2249 | 
            +
             | 
| 2250 | 
            +
            		/* Is the given timeout valid? */
         | 
| 2251 | 
            +
            		if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
         | 
| 2252 | 
            +
            			/* Wait for the socket to become readable before checking again */
         | 
| 2253 | 
            +
            			wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
         | 
| 2254 | 
            +
            		} else {
         | 
| 2255 | 
            +
            			wait_ret = WAIT_TIMEOUT;
         | 
| 2256 | 
            +
            		}
         | 
| 2228 2257 |  | 
| 2229 2258 | 
             
            		if ( wait_ret == WAIT_TIMEOUT ) {
         | 
| 2230 2259 | 
             
            			WSACloseEvent( hEvent );
         | 
| @@ -2237,16 +2266,16 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2237 2266 | 
             
            			rb_thread_check_ints();
         | 
| 2238 2267 | 
             
            		} else if ( wait_ret == WAIT_FAILED ) {
         | 
| 2239 2268 | 
             
            			WSACloseEvent( hEvent );
         | 
| 2240 | 
            -
            			rb_raise(  | 
| 2269 | 
            +
            			rb_raise( rb_eConnectionBad, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
         | 
| 2241 2270 | 
             
            		} else {
         | 
| 2242 2271 | 
             
            			WSACloseEvent( hEvent );
         | 
| 2243 | 
            -
            			rb_raise(  | 
| 2272 | 
            +
            			rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
         | 
| 2244 2273 | 
             
            		}
         | 
| 2245 2274 |  | 
| 2246 2275 | 
             
            		/* Check for connection errors (PQisBusy is true on connection errors) */
         | 
| 2247 2276 | 
             
            		if ( PQconsumeInput(conn) == 0 ) {
         | 
| 2248 2277 | 
             
            			WSACloseEvent( hEvent );
         | 
| 2249 | 
            -
            			rb_raise(  | 
| 2278 | 
            +
            			rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
         | 
| 2250 2279 | 
             
            		}
         | 
| 2251 2280 | 
             
            	}
         | 
| 2252 2281 |  | 
| @@ -2265,18 +2294,24 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2265 2294 | 
             
            	int ret;
         | 
| 2266 2295 | 
             
            	void *retval;
         | 
| 2267 2296 | 
             
            	rb_fdset_t sd_rset;
         | 
| 2297 | 
            +
            	struct timeval aborttime={0,0}, currtime, waittime;
         | 
| 2268 2298 | 
             
            #ifdef _WIN32
         | 
| 2269 2299 | 
             
            	rb_fdset_t crt_sd_rset;
         | 
| 2270 2300 | 
             
            #endif
         | 
| 2271 2301 |  | 
| 2272 2302 | 
             
            	if ( sd < 0 )
         | 
| 2273 | 
            -
            		 | 
| 2303 | 
            +
            		rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
         | 
| 2274 2304 |  | 
| 2275 2305 | 
             
            	/* Check for connection errors (PQisBusy is true on connection errors) */
         | 
| 2276 2306 | 
             
            	if ( PQconsumeInput(conn) == 0 )
         | 
| 2277 | 
            -
            		rb_raise(  | 
| 2307 | 
            +
            		rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
         | 
| 2308 | 
            +
             | 
| 2309 | 
            +
            	rb_fd_init( &sd_rset );
         | 
| 2278 2310 |  | 
| 2279 | 
            -
             | 
| 2311 | 
            +
            	if ( ptimeout ) {
         | 
| 2312 | 
            +
            		gettimeofday(&currtime, NULL);
         | 
| 2313 | 
            +
            		timeradd(&currtime, ptimeout, &aborttime);
         | 
| 2314 | 
            +
            	}
         | 
| 2280 2315 |  | 
| 2281 2316 | 
             
            	while ( !(retval=is_readable(conn)) ) {
         | 
| 2282 2317 | 
             
            		rb_fd_zero( &sd_rset );
         | 
| @@ -2290,8 +2325,19 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2290 2325 | 
             
            		create_crt_fd(&sd_rset, &crt_sd_rset);
         | 
| 2291 2326 | 
             
            #endif
         | 
| 2292 2327 |  | 
| 2293 | 
            -
            		 | 
| 2294 | 
            -
             | 
| 2328 | 
            +
            		if ( ptimeout ) {
         | 
| 2329 | 
            +
            			gettimeofday(&currtime, NULL);
         | 
| 2330 | 
            +
            			timersub(&aborttime, &currtime, &waittime);
         | 
| 2331 | 
            +
            		}
         | 
| 2332 | 
            +
             | 
| 2333 | 
            +
            		/* Is the given timeout valid? */
         | 
| 2334 | 
            +
            		if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
         | 
| 2335 | 
            +
            			/* Wait for the socket to become readable before checking again */
         | 
| 2336 | 
            +
            			ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout ? &waittime : NULL );
         | 
| 2337 | 
            +
            		} else {
         | 
| 2338 | 
            +
            			ret = 0;
         | 
| 2339 | 
            +
            		}
         | 
| 2340 | 
            +
             | 
| 2295 2341 |  | 
| 2296 2342 | 
             
            #ifdef _WIN32
         | 
| 2297 2343 | 
             
            		cleanup_crt_fd(&sd_rset, &crt_sd_rset);
         | 
| @@ -2311,7 +2357,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2311 2357 | 
             
            		/* Check for connection errors (PQisBusy is true on connection errors) */
         | 
| 2312 2358 | 
             
            		if ( PQconsumeInput(conn) == 0 ){
         | 
| 2313 2359 | 
             
            			rb_fd_term( &sd_rset );
         | 
| 2314 | 
            -
            			rb_raise(  | 
| 2360 | 
            +
            			rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
         | 
| 2315 2361 | 
             
            		}
         | 
| 2316 2362 | 
             
            	}
         | 
| 2317 2363 |  | 
| @@ -2325,7 +2371,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl | |
| 2325 2371 | 
             
            static void *
         | 
| 2326 2372 | 
             
            notify_readable(PGconn *conn)
         | 
| 2327 2373 | 
             
            {
         | 
| 2328 | 
            -
            	return (void*) | 
| 2374 | 
            +
            	return (void*)gvl_PQnotifies(conn);
         | 
| 2329 2375 | 
             
            }
         | 
| 2330 2376 |  | 
| 2331 2377 | 
             
            /*
         | 
| @@ -2761,7 +2807,7 @@ pgconn_set_client_encoding(VALUE self, VALUE str) | |
| 2761 2807 |  | 
| 2762 2808 | 
             
            /*
         | 
| 2763 2809 | 
             
             * call-seq:
         | 
| 2764 | 
            -
             *    conn.transaction { |conn| ... } ->  | 
| 2810 | 
            +
             *    conn.transaction { |conn| ... } -> result of the block
         | 
| 2765 2811 | 
             
             *
         | 
| 2766 2812 | 
             
             * Executes a +BEGIN+ at the start of the block,
         | 
| 2767 2813 | 
             
             * and a +COMMIT+ at the end of the block, or
         | 
| @@ -2773,13 +2819,14 @@ pgconn_transaction(VALUE self) | |
| 2773 2819 | 
             
            	PGconn *conn = pg_get_pgconn(self);
         | 
| 2774 2820 | 
             
            	PGresult *result;
         | 
| 2775 2821 | 
             
            	VALUE rb_pgresult;
         | 
| 2822 | 
            +
            	VALUE block_result = Qnil;
         | 
| 2776 2823 | 
             
            	int status;
         | 
| 2777 2824 |  | 
| 2778 2825 | 
             
            	if (rb_block_given_p()) {
         | 
| 2779 2826 | 
             
            		result = gvl_PQexec(conn, "BEGIN");
         | 
| 2780 2827 | 
             
            		rb_pgresult = pg_new_result(result, self);
         | 
| 2781 2828 | 
             
            		pg_result_check(rb_pgresult);
         | 
| 2782 | 
            -
            		rb_protect(rb_yield, self, &status);
         | 
| 2829 | 
            +
            		block_result = rb_protect(rb_yield, self, &status);
         | 
| 2783 2830 | 
             
            		if(status == 0) {
         | 
| 2784 2831 | 
             
            			result = gvl_PQexec(conn, "COMMIT");
         | 
| 2785 2832 | 
             
            			rb_pgresult = pg_new_result(result, self);
         | 
| @@ -2798,7 +2845,7 @@ pgconn_transaction(VALUE self) | |
| 2798 2845 | 
             
            		/* no block supplied? */
         | 
| 2799 2846 | 
             
            		rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
         | 
| 2800 2847 | 
             
            	}
         | 
| 2801 | 
            -
            	return  | 
| 2848 | 
            +
            	return block_result;
         | 
| 2802 2849 | 
             
            }
         | 
| 2803 2850 |  | 
| 2804 2851 |  | 
| @@ -2832,6 +2879,9 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str) | |
| 2832 2879 | 
             
            	 * double-quotes. */
         | 
| 2833 2880 | 
             
            	char buffer[NAMEDATALEN*2+2];
         | 
| 2834 2881 | 
             
            	unsigned int i=0,j=0;
         | 
| 2882 | 
            +
            #ifdef M17N_SUPPORTED
         | 
| 2883 | 
            +
            	rb_encoding* enc;
         | 
| 2884 | 
            +
            #endif
         | 
| 2835 2885 |  | 
| 2836 2886 | 
             
            	UNUSED( self );
         | 
| 2837 2887 |  | 
| @@ -2849,6 +2899,16 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str) | |
| 2849 2899 | 
             
            	buffer[j++] = '"';
         | 
| 2850 2900 | 
             
            	ret = rb_str_new(buffer,j);
         | 
| 2851 2901 | 
             
            	OBJ_INFECT(ret, in_str);
         | 
| 2902 | 
            +
             | 
| 2903 | 
            +
            #ifdef M17N_SUPPORTED
         | 
| 2904 | 
            +
            	if ( rb_obj_class(self) == rb_cPGconn ) {
         | 
| 2905 | 
            +
            		enc = pg_conn_enc_get( pg_get_pgconn(self) );
         | 
| 2906 | 
            +
            	} else {
         | 
| 2907 | 
            +
            		enc = rb_enc_get(in_str);
         | 
| 2908 | 
            +
            	}
         | 
| 2909 | 
            +
            	rb_enc_associate(ret, enc);
         | 
| 2910 | 
            +
            #endif
         | 
| 2911 | 
            +
             | 
| 2852 2912 | 
             
            	return ret;
         | 
| 2853 2913 | 
             
            }
         | 
| 2854 2914 |  |