pg 0.13.2-x86-mingw32 → 0.14.0.pre.353-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,32 +21,38 @@ static PGresult* pgresult_get( VALUE );
21
21
  * Result constructor
22
22
  */
23
23
  VALUE
24
- pg_new_result(PGresult *result, PGconn *conn)
24
+ pg_new_result(PGresult *result, VALUE rb_pgconn)
25
25
  {
26
+ PGconn *conn = pg_get_pgconn( rb_pgconn );
26
27
  VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, pgresult_gc_free, result);
27
28
  #ifdef M17N_SUPPORTED
28
29
  rb_encoding *enc = pg_conn_enc_get( conn );
29
30
  ENCODING_SET( val, rb_enc_to_index(enc) );
30
31
  #endif
31
32
 
33
+ rb_iv_set( val, "@connection", rb_pgconn );
34
+
32
35
  return val;
33
36
  }
34
37
 
35
38
  /*
36
- * Raises appropriate exception if PGresult is
37
- * in a bad state.
39
+ * call-seq:
40
+ * res.result -> nil
41
+ *
42
+ * Raises appropriate exception if PG::Result is in a bad state.
38
43
  */
39
- void
40
- pg_check_result(VALUE rb_pgconn, VALUE rb_pgresult)
44
+ VALUE
45
+ pg_result_check( VALUE self )
41
46
  {
42
47
  VALUE error, exception;
48
+ VALUE rb_pgconn = rb_iv_get( self, "@connection" );
43
49
  PGconn *conn = pg_get_pgconn(rb_pgconn);
44
50
  PGresult *result;
45
51
  #ifdef M17N_SUPPORTED
46
52
  rb_encoding *enc = pg_conn_enc_get( conn );
47
53
  #endif
48
54
 
49
- Data_Get_Struct(rb_pgresult, PGresult, result);
55
+ Data_Get_Struct(self, PGresult, result);
50
56
 
51
57
  if(result == NULL)
52
58
  {
@@ -59,9 +65,12 @@ pg_check_result(VALUE rb_pgconn, VALUE rb_pgresult)
59
65
  case PGRES_TUPLES_OK:
60
66
  case PGRES_COPY_OUT:
61
67
  case PGRES_COPY_IN:
68
+ #ifdef HAVE_CONST_PGRES_COPY_BOTH
69
+ case PGRES_COPY_BOTH:
70
+ #endif
62
71
  case PGRES_EMPTY_QUERY:
63
72
  case PGRES_COMMAND_OK:
64
- return;
73
+ return Qnil;
65
74
  case PGRES_BAD_RESPONSE:
66
75
  case PGRES_FATAL_ERROR:
67
76
  case PGRES_NONFATAL_ERROR:
@@ -77,10 +86,11 @@ pg_check_result(VALUE rb_pgconn, VALUE rb_pgresult)
77
86
  #endif
78
87
  exception = rb_exc_new3( rb_ePGerror, error );
79
88
  rb_iv_set( exception, "@connection", rb_pgconn );
80
- rb_iv_set( exception, "@result", rb_pgresult );
89
+ rb_iv_set( exception, "@result", self );
81
90
  rb_exc_raise( exception );
82
91
 
83
- return;
92
+ /* Not reached */
93
+ return Qnil;
84
94
  }
85
95
 
86
96
 
@@ -94,7 +104,7 @@ pg_check_result(VALUE rb_pgconn, VALUE rb_pgresult)
94
104
  * call-seq:
95
105
  * res.clear() -> nil
96
106
  *
97
- * Clears the PGresult object as the result of the query.
107
+ * Clears the PG::Result object as the result of the query.
98
108
  */
99
109
  VALUE
100
110
  pg_result_clear(VALUE self)
@@ -135,7 +145,7 @@ pgresult_get(VALUE self)
135
145
 
136
146
  /********************************************************************
137
147
  *
138
- * Document-class: PGresult
148
+ * Document-class: PG::Result
139
149
  *
140
150
  * The class to represent the query result tuples (rows).
141
151
  * An instance of this class is created as the result of every query.
@@ -153,7 +163,7 @@ pgresult_get(VALUE self)
153
163
  */
154
164
 
155
165
  /**************************************************************************
156
- * PGresult INSTANCE METHODS
166
+ * PG::Result INSTANCE METHODS
157
167
  **************************************************************************/
158
168
 
159
169
  /*
@@ -229,20 +239,20 @@ pgresult_error_message(VALUE self)
229
239
  *
230
240
  * begin
231
241
  * conn.exec( "SELECT * FROM nonexistant_table" )
232
- * rescue PGError => err
242
+ * rescue PG::Error => err
233
243
  * p [
234
- * result.error_field( PGresult::PG_DIAG_SEVERITY ),
235
- * result.error_field( PGresult::PG_DIAG_SQLSTATE ),
236
- * result.error_field( PGresult::PG_DIAG_MESSAGE_PRIMARY ),
237
- * result.error_field( PGresult::PG_DIAG_MESSAGE_DETAIL ),
238
- * result.error_field( PGresult::PG_DIAG_MESSAGE_HINT ),
239
- * result.error_field( PGresult::PG_DIAG_STATEMENT_POSITION ),
240
- * result.error_field( PGresult::PG_DIAG_INTERNAL_POSITION ),
241
- * result.error_field( PGresult::PG_DIAG_INTERNAL_QUERY ),
242
- * result.error_field( PGresult::PG_DIAG_CONTEXT ),
243
- * result.error_field( PGresult::PG_DIAG_SOURCE_FILE ),
244
- * result.error_field( PGresult::PG_DIAG_SOURCE_LINE ),
245
- * result.error_field( PGresult::PG_DIAG_SOURCE_FUNCTION ),
244
+ * result.error_field( PG::Result::PG_DIAG_SEVERITY ),
245
+ * result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
246
+ * result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
247
+ * result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
248
+ * result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
249
+ * result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
250
+ * result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
251
+ * result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
252
+ * result.error_field( PG::Result::PG_DIAG_CONTEXT ),
253
+ * result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
254
+ * result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
255
+ * result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
246
256
  * ]
247
257
  * end
248
258
  *
@@ -492,7 +502,7 @@ pgresult_fsize(VALUE self, VALUE index)
492
502
  static VALUE
493
503
  pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
494
504
  {
495
- VALUE ret;
505
+ VALUE val;
496
506
  PGresult *result;
497
507
  int i = NUM2INT(tup_num);
498
508
  int j = NUM2INT(field_num);
@@ -506,10 +516,19 @@ pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
506
516
  }
507
517
  if(PQgetisnull(result, i, j))
508
518
  return Qnil;
509
- ret = rb_tainted_str_new(PQgetvalue(result, i, j),
519
+ val = rb_tainted_str_new(PQgetvalue(result, i, j),
510
520
  PQgetlength(result, i, j));
511
- ASSOCIATE_INDEX(ret, self);
512
- return ret;
521
+
522
+ #ifdef M17N_SUPPORTED
523
+ /* associate client encoding for text format only */
524
+ if ( 0 == PQfformat(result, j) ) {
525
+ ASSOCIATE_INDEX( val, self );
526
+ } else {
527
+ rb_enc_associate( val, rb_ascii8bit_encoding() );
528
+ }
529
+ #endif
530
+
531
+ return val;
513
532
  }
514
533
 
515
534
  /*
@@ -612,7 +631,7 @@ pgresult_cmd_status(VALUE self)
612
631
  *
613
632
  * Returns the number of tuples (rows) affected by the SQL command.
614
633
  *
615
- * If the SQL command that generated the PGresult was not one of:
634
+ * If the SQL command that generated the PG::Result was not one of:
616
635
  * * +INSERT+
617
636
  * * +UPDATE+
618
637
  * * +DELETE+
@@ -706,19 +725,15 @@ pgresult_values(VALUE self)
706
725
  int field;
707
726
  int num_rows = PQntuples(result);
708
727
  int num_fields = PQnfields(result);
709
- VALUE ary = rb_ary_new2(num_rows);
728
+ VALUE rows[ num_rows ];
710
729
 
711
730
  for ( row = 0; row < num_rows; row++ ) {
712
- /* create new row */
713
- VALUE new_row = rb_ary_new2(num_fields);
731
+ VALUE new_row[ num_fields ];
714
732
 
715
- /* add to return array */
716
- rb_ary_store( ary, row, new_row );
717
-
718
- /* populate it */
733
+ /* populate the row */
719
734
  for ( field = 0; field < num_fields; field++ ) {
720
735
  if ( PQgetisnull(result, row, field) ) {
721
- rb_ary_store( new_row, field, Qnil );
736
+ new_row[ field ] = Qnil;
722
737
  }
723
738
  else {
724
739
  VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field),
@@ -732,16 +747,18 @@ pgresult_values(VALUE self)
732
747
  rb_enc_associate( val, rb_ascii8bit_encoding() );
733
748
  }
734
749
  #endif
735
-
736
- rb_ary_store( new_row, field, val );
750
+ new_row[ field ] = val;
737
751
  }
738
752
  }
753
+
754
+ rows[ row ] = rb_ary_new4( num_fields, new_row );
739
755
  }
740
- return ary;
756
+
757
+ return rb_ary_new4( num_rows, rows );
741
758
  }
742
759
 
743
760
 
744
- /*
761
+ /*
745
762
  * Make a Ruby array out of the encoded values from the specified
746
763
  * column in the given result.
747
764
  */
@@ -749,16 +766,17 @@ static VALUE
749
766
  make_column_result_array( VALUE self, int col )
750
767
  {
751
768
  PGresult *result = pgresult_get( self );
752
- int row = PQntuples( result );
753
- VALUE ary = rb_ary_new2( row );
769
+ int rows = PQntuples( result );
770
+ int i;
754
771
  VALUE val = Qnil;
772
+ VALUE results[ rows ];
755
773
 
756
774
  if ( col >= PQnfields(result) )
757
775
  rb_raise( rb_eIndexError, "no column %d in result", col );
758
776
 
759
- while ( row-- ) {
760
- val = rb_tainted_str_new( PQgetvalue(result, row, col),
761
- PQgetlength(result, row, col) );
777
+ for ( i=0; i < rows; i++ ) {
778
+ val = rb_tainted_str_new( PQgetvalue(result, i, col),
779
+ PQgetlength(result, i, col) );
762
780
 
763
781
  #ifdef M17N_SUPPORTED
764
782
  /* associate client encoding for text format only */
@@ -769,10 +787,10 @@ make_column_result_array( VALUE self, int col )
769
787
  }
770
788
  #endif
771
789
 
772
- rb_ary_store( ary, row, val );
790
+ results[ i ] = val;
773
791
  }
774
792
 
775
- return ary;
793
+ return rb_ary_new4( rows, results );
776
794
  }
777
795
 
778
796
 
@@ -840,19 +858,18 @@ pgresult_each(VALUE self)
840
858
  static VALUE
841
859
  pgresult_fields(VALUE self)
842
860
  {
843
- PGresult *result;
844
- VALUE ary;
845
- int n, i;
861
+ PGresult *result = pgresult_get( self );
862
+ int n = PQnfields( result );
863
+ VALUE fields[ n ];
864
+ int i;
846
865
 
847
- result = pgresult_get(self);
848
- n = PQnfields(result);
849
- ary = rb_ary_new2(n);
850
- for (i=0;i<n;i++) {
866
+ for ( i = 0; i < n; i++ ) {
851
867
  VALUE val = rb_tainted_str_new2(PQfname(result, i));
852
868
  ASSOCIATE_INDEX(val, self);
853
- rb_ary_push(ary, val);
869
+ fields[ i ] = val;
854
870
  }
855
- return ary;
871
+
872
+ return rb_ary_new4( n, fields );
856
873
  }
857
874
 
858
875
 
@@ -871,6 +888,8 @@ init_pg_result()
871
888
  rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
872
889
  rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
873
890
  rb_define_method(rb_cPGresult, "clear", pg_result_clear, 0);
891
+ rb_define_method(rb_cPGresult, "check", pg_result_check, 0);
892
+ rb_define_alias (rb_cPGresult, "check_result", "check");
874
893
  rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
875
894
  rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");
876
895
  rb_define_method(rb_cPGresult, "nfields", pgresult_nfields, 0);
Binary file
Binary file
data/lib/pg.rb CHANGED
@@ -19,7 +19,7 @@ end
19
19
  module PG
20
20
 
21
21
  # Library version
22
- VERSION = '0.13.2'
22
+ VERSION = '0.14.0.pre.353'
23
23
 
24
24
  # VCS revision
25
25
  REVISION = %q$Revision$
@@ -51,6 +51,13 @@ class PG::Connection
51
51
  return connopts.join(' ')
52
52
  end
53
53
 
54
+
55
+ # Backward-compatibility aliases for stuff that's moved into PG.
56
+ class << self
57
+ define_method( :isthreadsafe, &PG.method(:isthreadsafe) )
58
+ end
59
+
60
+
54
61
  end # class PG::Connection
55
62
 
56
63
  # Backward-compatible alias
@@ -65,6 +65,8 @@ until poll_status == PG::PGRES_POLLING_OK ||
65
65
  output_progress " negotiating SSL encryption."
66
66
  when PG::CONNECTION_SETENV
67
67
  output_progress " negotiating environment-driven parameter settings."
68
+ when PG::CONNECTION_NEEDED
69
+ output_progress " internal state: connect() needed."
68
70
  end
69
71
 
70
72
  # Check to see if it's finished or failed yet
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'pg'
6
+
7
+ # This is a minimal example of a function that can test an existing PG::Connection and
8
+ # reset it if necessary.
9
+
10
+ def check_connection( conn )
11
+ begin
12
+ conn.exec( "SELECT 1" )
13
+ rescue PG::Error => err
14
+ $stderr.puts "%p while testing connection: %s" % [ err.class, err.message ]
15
+ conn.reset
16
+ end
17
+ end
18
+
19
+ conn = PG.connect( dbname: 'test' )
20
+ check_connection( conn )
21
+
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set noet nosta sw=4 ts=4 :
3
+ #
4
+ # Quickly dump size information for a given database.
5
+ # Top twenty objects, and size per schema.
6
+ #
7
+ # Mahlon E. Smith <mahlon@martini.nu>
8
+ #
9
+ # Based on work by Jeff Davis <ruby@j-davis.com>.
10
+ #
11
+
12
+
13
+ begin
14
+ require 'ostruct'
15
+ require 'optparse'
16
+ require 'etc'
17
+ require 'pg'
18
+
19
+ rescue LoadError # 1.8 support
20
+ unless Object.const_defined?( :Gem )
21
+ require 'rubygems'
22
+ retry
23
+ end
24
+ raise
25
+ end
26
+
27
+ SCRIPT_VERSION = %q$Id$
28
+
29
+
30
+ ### Gather data and output it to $stdout.
31
+ ###
32
+ def report( opts )
33
+ db = PG.connect(
34
+ :dbname => opts.database,
35
+ :host => opts.host,
36
+ :port => opts.port,
37
+ :user => opts.user,
38
+ :password => opts.pass,
39
+ :sslmode => 'prefer'
40
+ )
41
+
42
+ # -----------------------------------------
43
+
44
+ db_info = db.exec %Q{
45
+ SELECT
46
+ count(oid) AS num_relations,
47
+ pg_size_pretty(pg_database_size('#{opts.database}')) AS dbsize
48
+ FROM
49
+ pg_class
50
+ }
51
+
52
+ puts '=' * 70
53
+ puts "Disk usage information for %s: (%d relations, %s total)" % [
54
+ opts.database,
55
+ db_info[0]['num_relations'],
56
+ db_info[0]['dbsize']
57
+ ]
58
+ puts '=' * 70
59
+
60
+ # -----------------------------------------
61
+
62
+ top_twenty = db.exec %q{
63
+ SELECT
64
+ relname AS name,
65
+ relkind AS kind,
66
+ pg_size_pretty(pg_relation_size(pg_class.oid)) AS size
67
+ FROM
68
+ pg_class
69
+ ORDER BY
70
+ pg_relation_size(pg_class.oid) DESC
71
+ LIMIT 20
72
+ }
73
+
74
+ puts 'Top twenty objects by size:'
75
+ puts '-' * 70
76
+ top_twenty.each do |row|
77
+ type = case row['kind']
78
+ when 'i'; 'index'
79
+ when 't'; 'toast'
80
+ when 'r'; 'table'
81
+ when 'S'; 'sequence'
82
+ else; '???'
83
+ end
84
+
85
+ puts "%40s %10s (%s)" % [ row['name'], row['size'], type ]
86
+ end
87
+ puts '-' * 70
88
+
89
+ # -----------------------------------------
90
+
91
+ schema_sizes = db.exec %q{
92
+ SELECT
93
+ table_schema,
94
+ pg_size_pretty( CAST( SUM(pg_total_relation_size(table_schema || '.' || table_name)) AS bigint)) AS size
95
+ FROM
96
+ information_schema.tables
97
+ GROUP BY
98
+ table_schema
99
+ ORDER BY
100
+ CAST( SUM(pg_total_relation_size(table_schema || '.' || table_name)) AS bigint ) DESC
101
+ }
102
+
103
+
104
+ puts 'Size per schema:'
105
+ puts '-' * 70
106
+ schema_sizes.each do |row|
107
+ puts "%20s %10s" % [ row['table_schema'], row['size'] ]
108
+ end
109
+ puts '-' * 70
110
+ puts
111
+
112
+ db.finish
113
+ end
114
+
115
+
116
+ ### Parse command line arguments. Return a struct of global options.
117
+ ###
118
+ def parse_args( args )
119
+ options = OpenStruct.new
120
+ options.database = Etc.getpwuid( Process.uid ).name
121
+ options.host = '127.0.0.1'
122
+ options.port = 5432
123
+ options.user = Etc.getpwuid( Process.uid ).name
124
+ options.sslmode = 'prefer'
125
+ options.interval = 5
126
+
127
+ opts = OptionParser.new do |opts|
128
+ opts.banner = "Usage: #{$0} [options]"
129
+
130
+ opts.separator ''
131
+ opts.separator 'Connection options:'
132
+
133
+ opts.on( '-d', '--database DBNAME',
134
+ "specify the database to connect to (default: \"#{options.database}\")" ) do |db|
135
+ options.database = db
136
+ end
137
+
138
+ opts.on( '-h', '--host HOSTNAME', 'database server host' ) do |host|
139
+ options.host = host
140
+ end
141
+
142
+ opts.on( '-p', '--port PORT', Integer,
143
+ "database server port (default: \"#{options.port}\")" ) do |port|
144
+ options.port = port
145
+ end
146
+
147
+ opts.on( '-U', '--user NAME',
148
+ "database user name (default: \"#{options.user}\")" ) do |user|
149
+ options.user = user
150
+ end
151
+
152
+ opts.on( '-W', 'force password prompt' ) do |pw|
153
+ print 'Password: '
154
+ begin
155
+ system 'stty -echo'
156
+ options.pass = gets.chomp
157
+ ensure
158
+ system 'stty echo'
159
+ puts
160
+ end
161
+ end
162
+
163
+ opts.separator ''
164
+ opts.separator 'Other options:'
165
+
166
+ opts.on_tail( '--help', 'show this help, then exit' ) do
167
+ $stderr.puts opts
168
+ exit
169
+ end
170
+
171
+ opts.on_tail( '--version', 'output version information, then exit' ) do
172
+ puts SCRIPT_VERSION
173
+ exit
174
+ end
175
+ end
176
+
177
+ opts.parse!( args )
178
+ return options
179
+ end
180
+
181
+
182
+ if __FILE__ == $0
183
+ opts = parse_args( ARGV )
184
+ report( opts )
185
+ end
186
+