pg 0.10.0 → 0.10.1pre209

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,125 +1,22 @@
1
1
  require 'pp'
2
2
  require 'mkmf'
3
3
 
4
+
4
5
  if pgdir = with_config( 'pg' )
5
6
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
6
7
  end
7
8
 
9
+ dir_config 'pg'
8
10
 
9
- ### Turn a version string into a Comparable binary datastructure
10
- def vvec( version )
11
- version.split( '.' ).collect {|i| Integer(i) }.pack( 'N*' )
12
- end
13
-
14
-
15
- if vvec(RUBY_VERSION) < vvec('1.8')
16
- puts 'This library is for ruby-1.8 or higher.'
17
- exit 1
18
- end
19
-
20
- if ENV['CROSS_COMPILING']
21
-
22
- $LDFLAGS << " -L#{CONFIG['libdir']}"
23
-
24
- # Link against all required libraries for static build, if they are available
25
- have_library( 'gdi32', 'CreateDC' ) && append_library( $libs, 'gdi32' )
26
- have_library( 'secur32' ) && append_library( $libs, 'secur32' )
27
- have_library( 'crypto', 'BIO_new' ) && append_library( $libs, 'crypto' )
28
- have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
29
-
11
+ if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
12
+ $stderr.puts "Using config values from %s" % [ pgconfig ]
13
+ $CPPFLAGS << " -I%s" % [ `#{pgconfig} --includedir`.chomp ]
14
+ $LDFLAGS << " -L%s" % [ `#{pgconfig} --libdir`.chomp ]
30
15
  else
31
- pgconfig = with_config( 'pg-config' ) || 'pg_config'
32
- if pgconfig = find_executable( pgconfig )
33
- $CFLAGS << " " + `#{pgconfig} --cflags`.chomp
34
- $CPPFLAGS << " -I%s" % [ `#{pgconfig} --includedir`.chomp ]
35
- $LDFLAGS << " -L%s" % [ `#{pgconfig} --libdir`.chomp ]
36
- end
37
-
38
- # Sort out the universal vs. single-archicture build problems on MacOS X
39
- if RUBY_PLATFORM.include?( 'darwin' )
40
- puts "MacOS X build: fixing architecture flags:"
41
- ruby_archs = Config::CONFIG['CFLAGS'].scan( /-arch (\S+)/ ).flatten
42
- $stderr.puts "Ruby cflags: %p" % [ Config::CONFIG['CFLAGS'] ]
43
-
44
- # Only keep the '-arch <a>' flags present in both the cflags reported
45
- # by pg_config and those that Ruby specifies.
46
- commonflags = nil
47
- if ENV['ARCHFLAGS']
48
- puts " using the value in ARCHFLAGS environment variable (%p)." % [ ENV['ARCHFLAGS'] ]
49
- common_archs = ENV['ARCHFLAGS'].scan( /-arch\s+(\S+)/ ).flatten
50
-
51
- # Warn if the ARCHFLAGS doesn't have at least one architecture in
52
- # common with the running ruby.
53
- if ( (common_archs & ruby_archs).empty? )
54
- $stderr.puts '',
55
- "*** Your ARCHFLAGS setting doesn't seem to contain an architecture in common",
56
- "with the running ruby interpreter (%p vs. %p)" % [ common_archs, ruby_archs ],
57
- "I'll continue anyway, but if it fails, try unsetting ARCHFLAGS."
58
- end
59
-
60
- commonflags = ENV['ARCHFLAGS']
61
- end
62
-
63
- if pgconfig
64
- puts " finding flags common to both Ruby and PostgreSQL..."
65
- archflags = []
66
- pgcflags = `#{pgconfig} --cflags`.chomp
67
- pgarchs = pgcflags.scan( /-arch\s+(\S+)/ ).flatten
68
- pgarchs.each do |arch|
69
- puts " testing for architecture: %p" % [ arch ]
70
- archflags << "-arch #{arch}" if ruby_archs.include?( arch )
71
- end
72
-
73
- if archflags.empty?
74
- $stderr.puts '',
75
- "*** Your PostgreSQL installation doesn't seem to have an architecture " +
76
- "in common with the running ruby interpreter (%p vs. %p)" %
77
- [ pgarchs, ruby_archs ],
78
- "I'll continue anyway, but if it fails, try setting ARCHFLAGS."
79
- else
80
- commonflags = archflags.join(' ')
81
- puts " common arch flags: %s" % [ commonflags ]
82
- end
83
- else
84
- $stderr.puts %{
85
- =========== WARNING ===========
86
-
87
- You are building this extension on OS X without setting the
88
- ARCHFLAGS environment variable, and pg_config wasn't found in
89
- your PATH. If you are seeing this message, that means that the
90
- build will probably fail.
91
-
92
- If it does, you can correct this by either including the path
93
- to 'pg_config' in your PATH or setting the environment variable
94
- ARCHFLAGS to '-arch <arch>' before building.
95
-
96
- For example:
97
- (in bash) $ export PATH=/opt/local/lib/postgresql84/bin:$PATH
98
- $ export ARCHFLAGS='-arch x86_64'
99
- (in tcsh) % set path = ( /opt/local/lib/postgresql84/bin $PATH )
100
- % setenv ARCHFLAGS '-arch x86_64'
101
-
102
- Then try building again.
103
-
104
- ===================================
105
- }.gsub( /^\t+/, ' ' )
106
- end
107
-
108
- if commonflags
109
- $CFLAGS.gsub!( /-arch\s+\S+ /, '' )
110
- $LDFLAGS.gsub!( /-arch\s+\S+ /, '' )
111
- CONFIG['LDSHARED'].gsub!( /-arch\s+\S+ /, '' )
112
-
113
- $CFLAGS << ' ' << commonflags
114
- $LDFLAGS << ' ' << commonflags
115
- CONFIG['LDSHARED'] << ' ' << commonflags
116
- end
117
- end
16
+ $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
17
+ " --with-pg-config=/path/to/pg_config"
118
18
  end
119
19
 
120
- dir_config 'pg'
121
-
122
-
123
20
  find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
124
21
  find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
125
22
 
@@ -135,10 +32,14 @@ have_func 'PQprepare'
135
32
  have_func 'PQexecParams'
136
33
  have_func 'PQescapeString'
137
34
  have_func 'PQescapeStringConn'
35
+ have_func 'PQgetCancel'
138
36
  have_func 'lo_create'
139
37
  have_func 'pg_encoding_to_char'
140
38
  have_func 'PQsetClientEncoding'
141
39
 
40
+ $defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
41
+ have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
42
+
142
43
  # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
143
44
  have_header 'unistd.h' unless enable_config("static-build")
144
45
 
data/ext/pg.c CHANGED
@@ -9,7 +9,7 @@
9
9
  modified at: Wed Jan 20 16:41:51 1999
10
10
 
11
11
  $Author: ged $
12
- $Date: 2010/11/12 03:39:48 $
12
+ $Date: 2010/12/06 16:45:23 $
13
13
  ************************************************/
14
14
 
15
15
  #include "pg.h"
@@ -23,7 +23,7 @@ static VALUE rb_cPGconn;
23
23
  static VALUE rb_cPGresult;
24
24
  static VALUE rb_ePGError;
25
25
 
26
- static const char *VERSION = "0.10.0";
26
+ static const char *VERSION = "0.10.1";
27
27
 
28
28
 
29
29
  /* The following functions are part of libpq, but not
@@ -2046,7 +2046,7 @@ pgconn_flush(self)
2046
2046
  * conn.cancel() -> String
2047
2047
  *
2048
2048
  * Requests cancellation of the command currently being
2049
- * processed.
2049
+ * processed. (Only implemented in PostgreSQL >= 8.0)
2050
2050
  *
2051
2051
  * Returns +nil+ on success, or a string containing the
2052
2052
  * error message if a failure occurs.
@@ -2054,6 +2054,7 @@ pgconn_flush(self)
2054
2054
  static VALUE
2055
2055
  pgconn_cancel(VALUE self)
2056
2056
  {
2057
+ #ifdef HAVE_PQGETCANCEL
2057
2058
  char errbuf[256];
2058
2059
  PGcancel *cancel;
2059
2060
  VALUE retval;
@@ -2071,6 +2072,9 @@ pgconn_cancel(VALUE self)
2071
2072
 
2072
2073
  PQfreeCancel(cancel);
2073
2074
  return retval;
2075
+ #else
2076
+ rb_notimplement();
2077
+ #endif
2074
2078
  }
2075
2079
 
2076
2080
 
@@ -2136,7 +2140,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2136
2140
  int ret;
2137
2141
  struct timeval timeout;
2138
2142
  struct timeval *ptimeout = NULL;
2139
- VALUE timeout_in, relname = Qnil, be_pid = Qnil;
2143
+ VALUE timeout_in, relname = Qnil, be_pid = Qnil, extra = Qnil;
2140
2144
  double timeout_sec;
2141
2145
  fd_set sd_rset;
2142
2146
 
@@ -2169,10 +2173,13 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2169
2173
 
2170
2174
  relname = rb_tainted_str_new2( notification->relname );
2171
2175
  be_pid = INT2NUM( notification->be_pid );
2176
+ #ifdef HAVE_ST_NOTIFY_EXTRA
2177
+ extra = rb_str_new2( notification->extra );
2178
+ #endif
2172
2179
  PQfreemem( notification );
2173
2180
 
2174
2181
  if ( rb_block_given_p() )
2175
- rb_yield_splat( rb_ary_new3(2, relname, be_pid) );
2182
+ rb_yield_values( 3, relname, be_pid, extra );
2176
2183
 
2177
2184
  return relname;
2178
2185
  }
data/lib/pg.rb CHANGED
@@ -1,13 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pathname'
4
3
  require 'rbconfig'
5
4
 
6
5
  # Load the correct version if it's a Windows binary gem
7
6
  if RUBY_PLATFORM =~/(mswin|mingw)/i
8
7
  major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
9
8
  raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
10
- require "#{major_minor}/pg_ext"
9
+
10
+ begin
11
+ require "#{major_minor}/pg_ext"
12
+ rescue LoadError
13
+ require 'pg_ext'
14
+ end
11
15
  else
12
16
  require 'pg_ext'
13
17
  end
data/rake/hg.rb CHANGED
@@ -83,6 +83,15 @@ unless defined?( HG_DOTDIR )
83
83
  return paths
84
84
  end
85
85
 
86
+ ### Return the list of files which are not of status 'clean'
87
+ def get_uncommitted_files
88
+ list = read_command_output( 'hg', 'status', '-n', '--color', 'never' )
89
+ list = list.split( /\n/ )
90
+
91
+ trace "Changed files: %p" % [ list ]
92
+ return list
93
+ end
94
+
86
95
  ### Return the list of files which are of status 'unknown'
87
96
  def get_unknown_files
88
97
  list = read_command_output( 'hg', 'status', '-un', '--color', 'never' )
@@ -149,11 +158,21 @@ unless defined?( HG_DOTDIR )
149
158
 
150
159
  desc "Prepare for a new release"
151
160
  task :prep_release do
161
+ uncommitted_files = get_uncommitted_files()
162
+ unless uncommitted_files.empty?
163
+ log "Uncommitted files:\n",
164
+ *uncommitted_files.map {|fn| " #{fn}\n" }
165
+ ask_for_confirmation( "\nRelease anyway?", true ) do
166
+ log "Okay, releasing with uncommitted versions."
167
+ end
168
+ end
169
+
152
170
  tags = get_tags()
153
171
  rev = get_current_rev()
172
+ pkg_version_tag = "v#{PKG_VERSION}"
154
173
 
155
174
  # Look for a tag for the current release version, and if it exists abort
156
- if tags.include?( PKG_VERSION )
175
+ if tags.include?( pkg_version_tag )
157
176
  error "Version #{PKG_VERSION} already has a tag. Did you mean " +
158
177
  "to increment the version in #{VERSION_FILE}?"
159
178
  fail
@@ -164,8 +183,8 @@ unless defined?( HG_DOTDIR )
164
183
  run 'hg', 'sign'
165
184
 
166
185
  # Tag the current rev
167
- log "Tagging rev #{rev} as #{PKG_VERSION}"
168
- run 'hg', 'tag', PKG_VERSION
186
+ log "Tagging rev #{rev} as #{pkg_version_tag}"
187
+ run 'hg', 'tag', pkg_version_tag
169
188
 
170
189
  # Offer to push
171
190
  Rake::Task['hg:push'].invoke
@@ -229,6 +248,18 @@ unless defined?( HG_DOTDIR )
229
248
  end
230
249
 
231
250
 
251
+ desc "Update to tip"
252
+ task :update do
253
+ run 'hg', 'update'
254
+ end
255
+
256
+
257
+ desc "Clobber all changes (hg up -C)"
258
+ task :update_and_clobber do
259
+ run 'hg', 'update', '-C'
260
+ end
261
+
262
+
232
263
  desc "Check the current code in if tests pass"
233
264
  task :checkin => ['hg:pull', 'hg:newfiles', 'test', COMMIT_MSG_FILE] do
234
265
  targets = get_target_args()
@@ -47,6 +47,7 @@ begin
47
47
  ### Task: spec
48
48
  desc "Run specs"
49
49
  task :spec => 'spec:doc'
50
+ task :specs => :spec
50
51
 
51
52
  namespace :spec do
52
53
  desc "Run rspec every time there's a change to one of the files"
@@ -161,15 +161,18 @@ module PgTestingHelpers
161
161
  datadir = testdir + 'data'
162
162
  pidfile = datadir + 'postmaster.pid'
163
163
  if pidfile.exist? && pid = pidfile.read.chomp.to_i
164
+ $stderr.puts "pidfile (%p) exists: %d" % [ pidfile, pid ]
164
165
  begin
165
166
  Process.kill( 0, pid )
166
167
  rescue Errno::ESRCH
167
- trace "No postmaster running for %s" % [ datadir ]
168
+ $stderr.puts "No postmaster running for %s" % [ datadir ]
168
169
  # Process isn't alive, so don't try to stop it
169
170
  else
170
- trace "Stopping lingering database at PID %d" % [ pid ]
171
+ $stderr.puts "Stopping lingering database at PID %d" % [ pid ]
171
172
  run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
172
173
  end
174
+ else
175
+ $stderr.puts "No pidfile (%p)" % [ pidfile ]
173
176
  end
174
177
  end
175
178
  end
@@ -196,20 +199,19 @@ module PgTestingHelpers
196
199
  begin
197
200
  unless (@test_pgdata+"postgresql.conf").exist?
198
201
  FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
199
- trace "Running initdb"
202
+ $stderr.puts "Running initdb"
200
203
  log_and_run @logfile, 'initdb', '--no-locale', '-D', @test_pgdata.to_s
201
204
  end
202
205
 
203
206
  trace "Starting postgres"
204
207
  log_and_run @logfile, 'pg_ctl', '-w', '-o', "-k #{@test_directory.to_s.inspect}",
205
208
  '-D', @test_pgdata.to_s, 'start'
209
+ sleep 2
210
+
211
+ $stderr.puts "Creating the test DB"
212
+ log_and_run @logfile, 'psql', '-e', '-c', 'DROP DATABASE IF EXISTS test', 'postgres'
213
+ log_and_run @logfile, 'createdb', '-e', 'test'
206
214
 
207
- if `psql -l` =~ /^\s*test\s/
208
- trace "Dropping the test DB"
209
- log_and_run @logfile, 'dropdb', 'test'
210
- end
211
- trace "Creating the test DB"
212
- log_and_run @logfile, 'createdb', 'test'
213
215
  rescue => err
214
216
  $stderr.puts "%p during test setup: %s" % [ err.class, err.message ]
215
217
  $stderr.puts "See #{@logfile} for details."
@@ -289,6 +289,116 @@ describe PGconn do
289
289
  @conn.exec( 'UNLISTEN woo' )
290
290
  end
291
291
 
292
+ context "under PostgreSQL 9" do
293
+
294
+ before( :each ) do
295
+ pending "only works under PostgreSQL 9" if @conn.server_version < 9_00_00
296
+ end
297
+
298
+ it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
299
+ "any number of arguments" do
300
+
301
+ @conn.exec( 'ROLLBACK' )
302
+ @conn.exec( 'LISTEN knees' )
303
+
304
+ pid = fork do
305
+ conn = PGconn.connect( @conninfo )
306
+ conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
307
+ conn.finish
308
+ exit!
309
+ end
310
+
311
+ Process.wait( pid )
312
+
313
+ event, pid, msg = nil
314
+ @conn.wait_for_notify( 10 ) do |*args|
315
+ event, pid, msg = *args
316
+ end
317
+ @conn.exec( 'UNLISTEN woo' )
318
+
319
+ event.should == 'knees'
320
+ pid.should be_a_kind_of( Integer )
321
+ msg.should == 'skirt and boots'
322
+ end
323
+
324
+ it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
325
+ "two arguments" do
326
+
327
+ @conn.exec( 'ROLLBACK' )
328
+ @conn.exec( 'LISTEN knees' )
329
+
330
+ pid = fork do
331
+ conn = PGconn.connect( @conninfo )
332
+ conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
333
+ conn.finish
334
+ exit!
335
+ end
336
+
337
+ Process.wait( pid )
338
+
339
+ event, pid, msg = nil
340
+ @conn.wait_for_notify( 10 ) do |arg1, arg2|
341
+ event, pid, msg = arg1, arg2
342
+ end
343
+ @conn.exec( 'UNLISTEN woo' )
344
+
345
+ event.should == 'knees'
346
+ pid.should be_a_kind_of( Integer )
347
+ msg.should be_nil()
348
+ end
349
+
350
+ it "calls the block supplied to wait_for_notify with the notify payload if it " +
351
+ "doesn't accept arguments" do
352
+
353
+ @conn.exec( 'ROLLBACK' )
354
+ @conn.exec( 'LISTEN knees' )
355
+
356
+ pid = fork do
357
+ conn = PGconn.connect( @conninfo )
358
+ conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
359
+ conn.finish
360
+ exit!
361
+ end
362
+
363
+ Process.wait( pid )
364
+
365
+ notification_received = false
366
+ @conn.wait_for_notify( 10 ) do
367
+ notification_received = true
368
+ end
369
+ @conn.exec( 'UNLISTEN woo' )
370
+
371
+ notification_received.should be_true()
372
+ end
373
+
374
+ it "calls the block supplied to wait_for_notify with the notify payload if it accepts " +
375
+ "three arguments" do
376
+
377
+ @conn.exec( 'ROLLBACK' )
378
+ @conn.exec( 'LISTEN knees' )
379
+
380
+ pid = fork do
381
+ conn = PGconn.connect( @conninfo )
382
+ conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
383
+ conn.finish
384
+ exit!
385
+ end
386
+
387
+ Process.wait( pid )
388
+
389
+ event, pid, msg = nil
390
+ @conn.wait_for_notify( 10 ) do |arg1, arg2, arg3|
391
+ event, pid, msg = arg1, arg2, arg3
392
+ end
393
+ @conn.exec( 'UNLISTEN woo' )
394
+
395
+ event.should == 'knees'
396
+ pid.should be_a_kind_of( Integer )
397
+ msg.should == 'skirt and boots'
398
+ end
399
+
400
+ end
401
+
292
402
  it "yields the result if block is given to exec" do
293
403
  rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
294
404
  values = []
@@ -343,7 +453,7 @@ describe PGconn do
343
453
  @conn.block( 0.1 )
344
454
  finish = Time.now
345
455
 
346
- (finish - start).should be_close( 0.1, 0.05 )
456
+ (finish - start).should be_within( 0.05 ).of( 0.1 )
347
457
  end
348
458
 
349
459