autocompl 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/lib/autocompl/repository.rb +11 -1
  3. data/lib/autocompl/version.rb +1 -1
  4. data/test/dummy/log/development.log +467 -0
  5. data/test/dummy/log/test.log +3 -0
  6. data/test/dummy/vendor/bundle/ruby/2.3.0/bin/console +23 -0
  7. data/test/dummy/vendor/bundle/ruby/2.3.0/cache/pg-0.19.0.gem +0 -0
  8. data/test/dummy/vendor/bundle/ruby/2.3.0/cache/pq-0.0.1.gem +0 -0
  9. data/test/dummy/vendor/bundle/ruby/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/pg-0.19.0/gem.build_complete +0 -0
  10. data/test/dummy/vendor/bundle/ruby/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/pg-0.19.0/gem_make.out +78 -0
  11. data/test/dummy/vendor/bundle/ruby/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/pg-0.19.0/mkmf.log +1346 -0
  12. data/test/dummy/vendor/bundle/ruby/2.3.0/extensions/x86_64-darwin-15/2.3.0-static/pg-0.19.0/pg_ext.bundle +0 -0
  13. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/BSDL +22 -0
  14. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ChangeLog +6378 -0
  15. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/Contributors.rdoc +46 -0
  16. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/History.rdoc +363 -0
  17. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/LICENSE +56 -0
  18. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/Manifest.txt +85 -0
  19. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/POSTGRES +23 -0
  20. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/README-OS_X.rdoc +68 -0
  21. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/README-Windows.rdoc +56 -0
  22. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/README.ja.rdoc +14 -0
  23. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/README.rdoc +168 -0
  24. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/Rakefile +216 -0
  25. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/Rakefile.cross +301 -0
  26. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/Makefile +261 -0
  27. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/errorcodes.def +947 -0
  28. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/errorcodes.rb +45 -0
  29. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/errorcodes.txt +467 -0
  30. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/extconf.h +38 -0
  31. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/extconf.rb +112 -0
  32. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/gvl_wrappers.c +13 -0
  33. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/gvl_wrappers.h +257 -0
  34. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/gvl_wrappers.o +0 -0
  35. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg.c +667 -0
  36. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg.h +395 -0
  37. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg.o +0 -0
  38. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_binary_decoder.c +162 -0
  39. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_binary_decoder.o +0 -0
  40. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_binary_encoder.c +162 -0
  41. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_binary_encoder.o +0 -0
  42. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_coder.c +500 -0
  43. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_coder.o +0 -0
  44. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_connection.c +4102 -0
  45. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_connection.o +0 -0
  46. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_copy_coder.c +591 -0
  47. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_copy_coder.o +0 -0
  48. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_errors.c +95 -0
  49. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_errors.o +0 -0
  50. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_ext.bundle +0 -0
  51. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_result.c +1271 -0
  52. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_result.o +0 -0
  53. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_text_decoder.c +421 -0
  54. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_text_decoder.o +0 -0
  55. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_text_encoder.c +683 -0
  56. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_text_encoder.o +0 -0
  57. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map.c +159 -0
  58. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map.o +0 -0
  59. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_all_strings.c +116 -0
  60. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_all_strings.o +0 -0
  61. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_class.c +239 -0
  62. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_class.o +0 -0
  63. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_column.c +312 -0
  64. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_column.o +0 -0
  65. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_mri_type.c +284 -0
  66. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_mri_type.o +0 -0
  67. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_oid.c +355 -0
  68. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_by_oid.o +0 -0
  69. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_in_ruby.c +299 -0
  70. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/pg_type_map_in_ruby.o +0 -0
  71. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/util.c +149 -0
  72. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/util.h +65 -0
  73. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/util.o +0 -0
  74. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/vc/pg.sln +26 -0
  75. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/vc/pg_18/pg.vcproj +216 -0
  76. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/ext/vc/pg_19/pg_19.vcproj +209 -0
  77. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg.rb +64 -0
  78. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/basic_type_mapping.rb +426 -0
  79. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/coder.rb +83 -0
  80. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/connection.rb +271 -0
  81. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/constants.rb +11 -0
  82. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/exceptions.rb +11 -0
  83. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/result.rb +30 -0
  84. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/text_decoder.rb +51 -0
  85. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/text_encoder.rb +35 -0
  86. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg/type_map_by_column.rb +15 -0
  87. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/lib/pg_ext.bundle +0 -0
  88. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/array_insert.rb +20 -0
  89. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/async_api.rb +106 -0
  90. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/async_copyto.rb +39 -0
  91. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/async_mixed.rb +56 -0
  92. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/check_conn.rb +21 -0
  93. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/copyfrom.rb +81 -0
  94. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/copyto.rb +19 -0
  95. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/cursor.rb +21 -0
  96. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/disk_usage_report.rb +186 -0
  97. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/issue-119.rb +94 -0
  98. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/losample.rb +69 -0
  99. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/minimal-testcase.rb +17 -0
  100. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/notify_wait.rb +72 -0
  101. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/pg_statistics.rb +294 -0
  102. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/replication_monitor.rb +231 -0
  103. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/test_binary_values.rb +33 -0
  104. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/wal_shipper.rb +434 -0
  105. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/sample/warehouse_partitions.rb +320 -0
  106. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/data/expected_trace.out +26 -0
  107. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/data/random_binary_data +0 -0
  108. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/helpers.rb +352 -0
  109. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/basic_type_mapping_spec.rb +305 -0
  110. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/connection_spec.rb +1676 -0
  111. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/result_spec.rb +449 -0
  112. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_by_class_spec.rb +138 -0
  113. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_by_column_spec.rb +222 -0
  114. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  115. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_by_oid_spec.rb +149 -0
  116. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_in_ruby_spec.rb +164 -0
  117. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_map_spec.rb +22 -0
  118. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg/type_spec.rb +777 -0
  119. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pg-0.19.0/spec/pg_spec.rb +50 -0
  120. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/Gemfile +4 -0
  121. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/LICENSE.txt +22 -0
  122. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/README.md +76 -0
  123. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/Rakefile +1 -0
  124. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/bin/console +7 -0
  125. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/lib/pq.rb +99 -0
  126. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/pq.gemspec +29 -0
  127. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/spec/helpers.rb +10 -0
  128. data/test/dummy/vendor/bundle/ruby/2.3.0/gems/pq-0.0.1/spec/queue_spec.rb +84 -0
  129. data/test/dummy/vendor/bundle/ruby/2.3.0/specifications/pg-0.19.0.gemspec +63 -0
  130. data/test/dummy/vendor/bundle/ruby/2.3.0/specifications/pq-0.0.1.gemspec +49 -0
  131. metadata +253 -1
@@ -0,0 +1,95 @@
1
+ /*
2
+ * pg_errors.c - Definition and lookup of error classes.
3
+ *
4
+ */
5
+
6
+ #include "pg.h"
7
+
8
+ VALUE rb_hErrors;
9
+ VALUE rb_ePGerror;
10
+ VALUE rb_eServerError;
11
+ VALUE rb_eUnableToSend;
12
+ VALUE rb_eConnectionBad;
13
+ VALUE rb_eInvalidResultStatus;
14
+ VALUE rb_eNoResultError;
15
+ VALUE rb_eInvalidChangeOfResultFields;
16
+
17
+ static VALUE
18
+ define_error_class(const char *name, const char *baseclass_code)
19
+ {
20
+ VALUE baseclass = rb_eServerError;
21
+ if(baseclass_code)
22
+ {
23
+ baseclass = rb_hash_aref( rb_hErrors, rb_str_new2(baseclass_code) );
24
+ }
25
+ return rb_define_class_under( rb_mPG, name, baseclass );
26
+ }
27
+
28
+ static void
29
+ register_error_class(const char *code, VALUE klass)
30
+ {
31
+ rb_hash_aset( rb_hErrors, rb_str_new2(code), klass );
32
+ }
33
+
34
+ /* Find a proper error class for the given SQLSTATE string
35
+ */
36
+ VALUE
37
+ lookup_error_class(const char *sqlstate)
38
+ {
39
+ VALUE klass;
40
+
41
+ if(sqlstate)
42
+ {
43
+ /* Find the proper error class by the 5-characters SQLSTATE. */
44
+ klass = rb_hash_aref( rb_hErrors, rb_str_new2(sqlstate) );
45
+ if(NIL_P(klass))
46
+ {
47
+ /* The given SQLSTATE couldn't be found. This might happen, if
48
+ * the server side uses a newer version than the client.
49
+ * Try to find a error class by using the 2-characters SQLSTATE.
50
+ */
51
+ klass = rb_hash_aref( rb_hErrors, rb_str_new(sqlstate, 2) );
52
+ if(NIL_P(klass))
53
+ {
54
+ /* Also the 2-characters SQLSTATE is unknown.
55
+ * Use the generic server error instead.
56
+ */
57
+ klass = rb_eServerError;
58
+ }
59
+ }
60
+ }
61
+ else
62
+ {
63
+ /* Unable to retrieve the PG_DIAG_SQLSTATE.
64
+ * Use the generic error instead.
65
+ */
66
+ klass = rb_eUnableToSend;
67
+ }
68
+
69
+ return klass;
70
+ }
71
+
72
+ void
73
+ init_pg_errors()
74
+ {
75
+ rb_hErrors = rb_hash_new();
76
+ rb_define_const( rb_mPG, "ERROR_CLASSES", rb_hErrors );
77
+
78
+ rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
79
+
80
+ /*************************
81
+ * PG::Error
82
+ *************************/
83
+ rb_define_alias( rb_ePGerror, "error", "message" );
84
+ rb_define_attr( rb_ePGerror, "connection", 1, 0 );
85
+ rb_define_attr( rb_ePGerror, "result", 1, 0 );
86
+
87
+ rb_eServerError = rb_define_class_under( rb_mPG, "ServerError", rb_ePGerror );
88
+ rb_eUnableToSend = rb_define_class_under( rb_mPG, "UnableToSend", rb_ePGerror );
89
+ rb_eConnectionBad = rb_define_class_under( rb_mPG, "ConnectionBad", rb_ePGerror );
90
+ rb_eInvalidResultStatus = rb_define_class_under( rb_mPG, "InvalidResultStatus", rb_ePGerror );
91
+ rb_eNoResultError = rb_define_class_under( rb_mPG, "NoResultError", rb_ePGerror );
92
+ rb_eInvalidChangeOfResultFields = rb_define_class_under( rb_mPG, "InvalidChangeOfResultFields", rb_ePGerror );
93
+
94
+ #include "errorcodes.def"
95
+ }
@@ -0,0 +1,1271 @@
1
+ /*
2
+ * pg_result.c - PG::Result class extension
3
+ * $Id: pg_result.c,v 982082c0d77b 2016/01/31 19:28:55 ged $
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+
9
+
10
+ VALUE rb_cPGresult;
11
+
12
+ static void pgresult_gc_free( t_pg_result * );
13
+ static VALUE pgresult_type_map_set( VALUE, VALUE );
14
+ static VALUE pgresult_s_allocate( VALUE );
15
+ static t_pg_result *pgresult_get_this( VALUE );
16
+ static t_pg_result *pgresult_get_this_safe( VALUE );
17
+
18
+
19
+
20
+ /*
21
+ * Global functions
22
+ */
23
+
24
+ /*
25
+ * Result constructor
26
+ */
27
+ VALUE
28
+ pg_new_result(PGresult *result, VALUE rb_pgconn)
29
+ {
30
+ int nfields = result ? PQnfields(result) : 0;
31
+ VALUE self = pgresult_s_allocate( rb_cPGresult );
32
+ t_pg_result *this;
33
+
34
+ this = (t_pg_result *)xmalloc(sizeof(*this) + sizeof(*this->fnames) * nfields);
35
+ DATA_PTR(self) = this;
36
+
37
+ this->pgresult = result;
38
+ this->connection = rb_pgconn;
39
+ this->typemap = pg_typemap_all_strings;
40
+ this->p_typemap = DATA_PTR( this->typemap );
41
+ this->autoclear = 0;
42
+ this->nfields = -1;
43
+ this->tuple_hash = Qnil;
44
+
45
+ PG_ENCODING_SET_NOCHECK(self, ENCODING_GET(rb_pgconn));
46
+
47
+ if( result ){
48
+ t_pg_connection *p_conn = pg_get_connection(rb_pgconn);
49
+ VALUE typemap = p_conn->type_map_for_results;
50
+
51
+ /* Type check is done when assigned to PG::Connection. */
52
+ t_typemap *p_typemap = DATA_PTR(typemap);
53
+
54
+ this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
55
+ this->p_typemap = DATA_PTR( this->typemap );
56
+ }
57
+
58
+ return self;
59
+ }
60
+
61
+ VALUE
62
+ pg_new_result_autoclear(PGresult *result, VALUE rb_pgconn)
63
+ {
64
+ VALUE self = pg_new_result(result, rb_pgconn);
65
+ t_pg_result *this = pgresult_get_this(self);
66
+ this->autoclear = 1;
67
+ return self;
68
+ }
69
+
70
+ /*
71
+ * call-seq:
72
+ * res.check -> nil
73
+ *
74
+ * Raises appropriate exception if PG::Result is in a bad state.
75
+ */
76
+ VALUE
77
+ pg_result_check( VALUE self )
78
+ {
79
+ t_pg_result *this = pgresult_get_this(self);
80
+ VALUE error, exception, klass;
81
+ char * sqlstate;
82
+
83
+ if(this->pgresult == NULL)
84
+ {
85
+ PGconn *conn = pg_get_pgconn(this->connection);
86
+ error = rb_str_new2( PQerrorMessage(conn) );
87
+ }
88
+ else
89
+ {
90
+ switch (PQresultStatus(this->pgresult))
91
+ {
92
+ case PGRES_TUPLES_OK:
93
+ case PGRES_COPY_OUT:
94
+ case PGRES_COPY_IN:
95
+ #ifdef HAVE_CONST_PGRES_COPY_BOTH
96
+ case PGRES_COPY_BOTH:
97
+ #endif
98
+ #ifdef HAVE_CONST_PGRES_SINGLE_TUPLE
99
+ case PGRES_SINGLE_TUPLE:
100
+ #endif
101
+ case PGRES_EMPTY_QUERY:
102
+ case PGRES_COMMAND_OK:
103
+ return self;
104
+ case PGRES_BAD_RESPONSE:
105
+ case PGRES_FATAL_ERROR:
106
+ case PGRES_NONFATAL_ERROR:
107
+ error = rb_str_new2( PQresultErrorMessage(this->pgresult) );
108
+ break;
109
+ default:
110
+ error = rb_str_new2( "internal error : unknown result status." );
111
+ }
112
+ }
113
+
114
+ PG_ENCODING_SET_NOCHECK( error, ENCODING_GET(self) );
115
+
116
+ sqlstate = PQresultErrorField( this->pgresult, PG_DIAG_SQLSTATE );
117
+ klass = lookup_error_class( sqlstate );
118
+ exception = rb_exc_new3( klass, error );
119
+ rb_iv_set( exception, "@connection", this->connection );
120
+ rb_iv_set( exception, "@result", this->pgresult ? self : Qnil );
121
+ rb_exc_raise( exception );
122
+
123
+ /* Not reached */
124
+ return self;
125
+ }
126
+
127
+
128
+ /*
129
+ * :TODO: This shouldn't be a global function, but it needs to be as long as pg_new_result
130
+ * doesn't handle blocks, check results, etc. Once connection and result are disentangled
131
+ * a bit more, I can make this a static pgresult_clear() again.
132
+ */
133
+
134
+ /*
135
+ * call-seq:
136
+ * res.clear() -> nil
137
+ *
138
+ * Clears the PG::Result object as the result of the query.
139
+ *
140
+ * If PG::Result#autoclear? is true then the result is marked as cleared
141
+ * and the underlying C struct will be cleared automatically by libpq.
142
+ *
143
+ */
144
+ VALUE
145
+ pg_result_clear(VALUE self)
146
+ {
147
+ t_pg_result *this = pgresult_get_this(self);
148
+ if( !this->autoclear )
149
+ PQclear(pgresult_get(self));
150
+ this->pgresult = NULL;
151
+ return Qnil;
152
+ }
153
+
154
+ /*
155
+ * call-seq:
156
+ * res.cleared? -> boolean
157
+ *
158
+ * Returns +true+ if the backend result memory has been free'd.
159
+ */
160
+ VALUE
161
+ pgresult_cleared_p( VALUE self )
162
+ {
163
+ t_pg_result *this = pgresult_get_this(self);
164
+ return this->pgresult ? Qfalse : Qtrue;
165
+ }
166
+
167
+ /*
168
+ * call-seq:
169
+ * res.autoclear? -> boolean
170
+ *
171
+ * Returns +true+ if the underlying C struct will be cleared automatically by libpq.
172
+ * Elsewise the result is cleared by PG::Result#clear or by the GC when it's no longer in use.
173
+ *
174
+ */
175
+ VALUE
176
+ pgresult_autoclear_p( VALUE self )
177
+ {
178
+ t_pg_result *this = pgresult_get_this(self);
179
+ return this->autoclear ? Qtrue : Qfalse;
180
+ }
181
+
182
+ /*
183
+ * DATA pointer functions
184
+ */
185
+
186
+ /*
187
+ * GC Mark function
188
+ */
189
+ static void
190
+ pgresult_gc_mark( t_pg_result *this )
191
+ {
192
+ int i;
193
+
194
+ if( !this ) return;
195
+ rb_gc_mark( this->connection );
196
+ rb_gc_mark( this->typemap );
197
+ rb_gc_mark( this->tuple_hash );
198
+
199
+ for( i=0; i < this->nfields; i++ ){
200
+ rb_gc_mark( this->fnames[i] );
201
+ }
202
+ }
203
+
204
+ /*
205
+ * GC Free function
206
+ */
207
+ static void
208
+ pgresult_gc_free( t_pg_result *this )
209
+ {
210
+ if( !this ) return;
211
+ if(this->pgresult != NULL && !this->autoclear)
212
+ PQclear(this->pgresult);
213
+
214
+ xfree(this);
215
+ }
216
+
217
+ /*
218
+ * Fetch the PG::Result object data pointer and check it's
219
+ * PGresult data pointer for sanity.
220
+ */
221
+ static t_pg_result *
222
+ pgresult_get_this_safe( VALUE self )
223
+ {
224
+ t_pg_result *this = pgresult_get_this(self);
225
+
226
+ if (this->pgresult == NULL) rb_raise(rb_ePGerror, "result has been cleared");
227
+ return this;
228
+ }
229
+
230
+ /*
231
+ * Fetch the PGresult pointer for the result object and check validity
232
+ *
233
+ * Note: This function is used externally by the sequel_pg gem,
234
+ * so do changes carefully.
235
+ *
236
+ */
237
+ PGresult*
238
+ pgresult_get(VALUE self)
239
+ {
240
+ t_pg_result *this = pgresult_get_this(self);
241
+
242
+ if (this->pgresult == NULL) rb_raise(rb_ePGerror, "result has been cleared");
243
+ return this->pgresult;
244
+ }
245
+
246
+ /*
247
+ * Document-method: allocate
248
+ *
249
+ * call-seq:
250
+ * PG::Result.allocate -> result
251
+ */
252
+ static VALUE
253
+ pgresult_s_allocate( VALUE klass )
254
+ {
255
+ VALUE self = Data_Wrap_Struct( klass, pgresult_gc_mark, pgresult_gc_free, NULL );
256
+
257
+ return self;
258
+ }
259
+
260
+ static void pgresult_init_fnames(VALUE self)
261
+ {
262
+ t_pg_result *this = pgresult_get_this_safe(self);
263
+
264
+ if( this->nfields == -1 ){
265
+ int i;
266
+ int nfields = PQnfields(this->pgresult);
267
+
268
+ for( i=0; i<nfields; i++ ){
269
+ VALUE fname = rb_tainted_str_new2(PQfname(this->pgresult, i));
270
+ PG_ENCODING_SET_NOCHECK(fname, ENCODING_GET(self));
271
+ this->fnames[i] = rb_obj_freeze(fname);
272
+ this->nfields = i + 1;
273
+
274
+ RB_GC_GUARD(fname);
275
+ }
276
+ this->nfields = nfields;
277
+ }
278
+ }
279
+
280
+ /********************************************************************
281
+ *
282
+ * Document-class: PG::Result
283
+ *
284
+ * The class to represent the query result tuples (rows).
285
+ * An instance of this class is created as the result of every query.
286
+ * You may need to invoke the #clear method of the instance when finished with
287
+ * the result for better memory performance.
288
+ *
289
+ * Example:
290
+ * require 'pg'
291
+ * conn = PG.connect(:dbname => 'test')
292
+ * res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
293
+ * res.getvalue(0,0) # '1'
294
+ * res[0]['b'] # '2'
295
+ * res[0]['c'] # nil
296
+ *
297
+ */
298
+
299
+ /**************************************************************************
300
+ * PG::Result INSTANCE METHODS
301
+ **************************************************************************/
302
+
303
+ /*
304
+ * call-seq:
305
+ * res.result_status() -> Fixnum
306
+ *
307
+ * Returns the status of the query. The status value is one of:
308
+ * * +PGRES_EMPTY_QUERY+
309
+ * * +PGRES_COMMAND_OK+
310
+ * * +PGRES_TUPLES_OK+
311
+ * * +PGRES_COPY_OUT+
312
+ * * +PGRES_COPY_IN+
313
+ * * +PGRES_BAD_RESPONSE+
314
+ * * +PGRES_NONFATAL_ERROR+
315
+ * * +PGRES_FATAL_ERROR+
316
+ * * +PGRES_COPY_BOTH+
317
+ */
318
+ static VALUE
319
+ pgresult_result_status(VALUE self)
320
+ {
321
+ return INT2FIX(PQresultStatus(pgresult_get(self)));
322
+ }
323
+
324
+ /*
325
+ * call-seq:
326
+ * res.res_status( status ) -> String
327
+ *
328
+ * Returns the string representation of status +status+.
329
+ *
330
+ */
331
+ static VALUE
332
+ pgresult_res_status(VALUE self, VALUE status)
333
+ {
334
+ VALUE ret = rb_tainted_str_new2(PQresStatus(NUM2INT(status)));
335
+ PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET(self));
336
+ return ret;
337
+ }
338
+
339
+ /*
340
+ * call-seq:
341
+ * res.error_message() -> String
342
+ *
343
+ * Returns the error message of the command as a string.
344
+ */
345
+ static VALUE
346
+ pgresult_error_message(VALUE self)
347
+ {
348
+ VALUE ret = rb_tainted_str_new2(PQresultErrorMessage(pgresult_get(self)));
349
+ PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET(self));
350
+ return ret;
351
+ }
352
+
353
+ /*
354
+ * call-seq:
355
+ * res.error_field(fieldcode) -> String
356
+ *
357
+ * Returns the individual field of an error.
358
+ *
359
+ * +fieldcode+ is one of:
360
+ * * +PG_DIAG_SEVERITY+
361
+ * * +PG_DIAG_SQLSTATE+
362
+ * * +PG_DIAG_MESSAGE_PRIMARY+
363
+ * * +PG_DIAG_MESSAGE_DETAIL+
364
+ * * +PG_DIAG_MESSAGE_HINT+
365
+ * * +PG_DIAG_STATEMENT_POSITION+
366
+ * * +PG_DIAG_INTERNAL_POSITION+
367
+ * * +PG_DIAG_INTERNAL_QUERY+
368
+ * * +PG_DIAG_CONTEXT+
369
+ * * +PG_DIAG_SOURCE_FILE+
370
+ * * +PG_DIAG_SOURCE_LINE+
371
+ * * +PG_DIAG_SOURCE_FUNCTION+
372
+ *
373
+ * An example:
374
+ *
375
+ * begin
376
+ * conn.exec( "SELECT * FROM nonexistant_table" )
377
+ * rescue PG::Error => err
378
+ * p [
379
+ * err.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
380
+ * err.result.error_field( PG::Result::PG_DIAG_SQLSTATE ),
381
+ * err.result.error_field( PG::Result::PG_DIAG_MESSAGE_PRIMARY ),
382
+ * err.result.error_field( PG::Result::PG_DIAG_MESSAGE_DETAIL ),
383
+ * err.result.error_field( PG::Result::PG_DIAG_MESSAGE_HINT ),
384
+ * err.result.error_field( PG::Result::PG_DIAG_STATEMENT_POSITION ),
385
+ * err.result.error_field( PG::Result::PG_DIAG_INTERNAL_POSITION ),
386
+ * err.result.error_field( PG::Result::PG_DIAG_INTERNAL_QUERY ),
387
+ * err.result.error_field( PG::Result::PG_DIAG_CONTEXT ),
388
+ * err.result.error_field( PG::Result::PG_DIAG_SOURCE_FILE ),
389
+ * err.result.error_field( PG::Result::PG_DIAG_SOURCE_LINE ),
390
+ * err.result.error_field( PG::Result::PG_DIAG_SOURCE_FUNCTION ),
391
+ * ]
392
+ * end
393
+ *
394
+ * Outputs:
395
+ *
396
+ * ["ERROR", "42P01", "relation \"nonexistant_table\" does not exist", nil, nil,
397
+ * "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
398
+ */
399
+ static VALUE
400
+ pgresult_error_field(VALUE self, VALUE field)
401
+ {
402
+ PGresult *result = pgresult_get( self );
403
+ int fieldcode = NUM2INT( field );
404
+ char * fieldstr = PQresultErrorField( result, fieldcode );
405
+ VALUE ret = Qnil;
406
+
407
+ if ( fieldstr ) {
408
+ ret = rb_tainted_str_new2( fieldstr );
409
+ PG_ENCODING_SET_NOCHECK( ret, ENCODING_GET(self ));
410
+ }
411
+
412
+ return ret;
413
+ }
414
+
415
+ /*
416
+ * call-seq:
417
+ * res.ntuples() -> Fixnum
418
+ *
419
+ * Returns the number of tuples in the query result.
420
+ */
421
+ static VALUE
422
+ pgresult_ntuples(VALUE self)
423
+ {
424
+ return INT2FIX(PQntuples(pgresult_get(self)));
425
+ }
426
+
427
+ static VALUE
428
+ pgresult_ntuples_for_enum(VALUE self, VALUE args, VALUE eobj)
429
+ {
430
+ return pgresult_ntuples(self);
431
+ }
432
+
433
+ /*
434
+ * call-seq:
435
+ * res.nfields() -> Integer
436
+ *
437
+ * Returns the number of columns in the query result.
438
+ */
439
+ static VALUE
440
+ pgresult_nfields(VALUE self)
441
+ {
442
+ return INT2NUM(PQnfields(pgresult_get(self)));
443
+ }
444
+
445
+ /*
446
+ * call-seq:
447
+ * res.fname( index ) -> String
448
+ *
449
+ * Returns the name of the column corresponding to _index_.
450
+ */
451
+ static VALUE
452
+ pgresult_fname(VALUE self, VALUE index)
453
+ {
454
+ VALUE fname;
455
+ PGresult *result = pgresult_get(self);
456
+ int i = NUM2INT(index);
457
+
458
+ if (i < 0 || i >= PQnfields(result)) {
459
+ rb_raise(rb_eArgError,"invalid field number %d", i);
460
+ }
461
+
462
+ fname = rb_tainted_str_new2(PQfname(result, i));
463
+ PG_ENCODING_SET_NOCHECK(fname, ENCODING_GET(self));
464
+ return rb_obj_freeze(fname);
465
+ }
466
+
467
+ /*
468
+ * call-seq:
469
+ * res.fnumber( name ) -> Fixnum
470
+ *
471
+ * Returns the index of the field specified by the string +name+.
472
+ * The given +name+ is treated like an identifier in an SQL command, that is,
473
+ * it is downcased unless double-quoted. For example, given a query result
474
+ * generated from the SQL command:
475
+ *
476
+ * result = conn.exec( %{SELECT 1 AS FOO, 2 AS "BAR"} )
477
+ *
478
+ * we would have the results:
479
+ *
480
+ * result.fname( 0 ) # => "foo"
481
+ * result.fname( 1 ) # => "BAR"
482
+ * result.fnumber( "FOO" ) # => 0
483
+ * result.fnumber( "foo" ) # => 0
484
+ * result.fnumber( "BAR" ) # => ArgumentError
485
+ * result.fnumber( %{"BAR"} ) # => 1
486
+ *
487
+ * Raises an ArgumentError if the specified +name+ isn't one of the field names;
488
+ * raises a TypeError if +name+ is not a String.
489
+ */
490
+ static VALUE
491
+ pgresult_fnumber(VALUE self, VALUE name)
492
+ {
493
+ int n;
494
+
495
+ Check_Type(name, T_STRING);
496
+
497
+ n = PQfnumber(pgresult_get(self), StringValueCStr(name));
498
+ if (n == -1) {
499
+ rb_raise(rb_eArgError,"Unknown field: %s", StringValueCStr(name));
500
+ }
501
+ return INT2FIX(n);
502
+ }
503
+
504
+ /*
505
+ * call-seq:
506
+ * res.ftable( column_number ) -> Integer
507
+ *
508
+ * Returns the Oid of the table from which the column _column_number_
509
+ * was fetched.
510
+ *
511
+ * Raises ArgumentError if _column_number_ is out of range or if
512
+ * the Oid is undefined for that column.
513
+ */
514
+ static VALUE
515
+ pgresult_ftable(VALUE self, VALUE column_number)
516
+ {
517
+ Oid n ;
518
+ int col_number = NUM2INT(column_number);
519
+ PGresult *pgresult = pgresult_get(self);
520
+
521
+ if( col_number < 0 || col_number >= PQnfields(pgresult))
522
+ rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
523
+
524
+ n = PQftable(pgresult, col_number);
525
+ return UINT2NUM(n);
526
+ }
527
+
528
+ /*
529
+ * call-seq:
530
+ * res.ftablecol( column_number ) -> Fixnum
531
+ *
532
+ * Returns the column number (within its table) of the table from
533
+ * which the column _column_number_ is made up.
534
+ *
535
+ * Raises ArgumentError if _column_number_ is out of range or if
536
+ * the column number from its table is undefined for that column.
537
+ */
538
+ static VALUE
539
+ pgresult_ftablecol(VALUE self, VALUE column_number)
540
+ {
541
+ int col_number = NUM2INT(column_number);
542
+ PGresult *pgresult = pgresult_get(self);
543
+
544
+ int n;
545
+
546
+ if( col_number < 0 || col_number >= PQnfields(pgresult))
547
+ rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
548
+
549
+ n = PQftablecol(pgresult, col_number);
550
+ return INT2FIX(n);
551
+ }
552
+
553
+ /*
554
+ * call-seq:
555
+ * res.fformat( column_number ) -> Fixnum
556
+ *
557
+ * Returns the format (0 for text, 1 for binary) of column
558
+ * _column_number_.
559
+ *
560
+ * Raises ArgumentError if _column_number_ is out of range.
561
+ */
562
+ static VALUE
563
+ pgresult_fformat(VALUE self, VALUE column_number)
564
+ {
565
+ PGresult *result = pgresult_get(self);
566
+ int fnumber = NUM2INT(column_number);
567
+ if (fnumber < 0 || fnumber >= PQnfields(result)) {
568
+ rb_raise(rb_eArgError, "Column number is out of range: %d",
569
+ fnumber);
570
+ }
571
+ return INT2FIX(PQfformat(result, fnumber));
572
+ }
573
+
574
+ /*
575
+ * call-seq:
576
+ * res.ftype( column_number ) -> Integer
577
+ *
578
+ * Returns the data type associated with _column_number_.
579
+ *
580
+ * The integer returned is the internal +OID+ number (in PostgreSQL)
581
+ * of the type. To get a human-readable value for the type, use the
582
+ * returned OID and the field's #fmod value with the format_type() SQL
583
+ * function:
584
+ *
585
+ * # Get the type of the second column of the result 'res'
586
+ * typename = conn.
587
+ * exec( "SELECT format_type($1,$2)", [res.ftype(1), res.fmod(1)] ).
588
+ * getvalue( 0, 0 )
589
+ *
590
+ * Raises an ArgumentError if _column_number_ is out of range.
591
+ */
592
+ static VALUE
593
+ pgresult_ftype(VALUE self, VALUE index)
594
+ {
595
+ PGresult* result = pgresult_get(self);
596
+ int i = NUM2INT(index);
597
+ if (i < 0 || i >= PQnfields(result)) {
598
+ rb_raise(rb_eArgError, "invalid field number %d", i);
599
+ }
600
+ return UINT2NUM(PQftype(result, i));
601
+ }
602
+
603
+ /*
604
+ * call-seq:
605
+ * res.fmod( column_number )
606
+ *
607
+ * Returns the type modifier associated with column _column_number_. See
608
+ * the #ftype method for an example of how to use this.
609
+ *
610
+ * Raises an ArgumentError if _column_number_ is out of range.
611
+ */
612
+ static VALUE
613
+ pgresult_fmod(VALUE self, VALUE column_number)
614
+ {
615
+ PGresult *result = pgresult_get(self);
616
+ int fnumber = NUM2INT(column_number);
617
+ int modifier;
618
+ if (fnumber < 0 || fnumber >= PQnfields(result)) {
619
+ rb_raise(rb_eArgError, "Column number is out of range: %d",
620
+ fnumber);
621
+ }
622
+ modifier = PQfmod(result,fnumber);
623
+
624
+ return INT2NUM(modifier);
625
+ }
626
+
627
+ /*
628
+ * call-seq:
629
+ * res.fsize( index )
630
+ *
631
+ * Returns the size of the field type in bytes. Returns <tt>-1</tt> if the field is variable sized.
632
+ *
633
+ * res = conn.exec("SELECT myInt, myVarChar50 FROM foo")
634
+ * res.size(0) => 4
635
+ * res.size(1) => -1
636
+ */
637
+ static VALUE
638
+ pgresult_fsize(VALUE self, VALUE index)
639
+ {
640
+ PGresult *result;
641
+ int i = NUM2INT(index);
642
+
643
+ result = pgresult_get(self);
644
+ if (i < 0 || i >= PQnfields(result)) {
645
+ rb_raise(rb_eArgError,"invalid field number %d", i);
646
+ }
647
+ return INT2NUM(PQfsize(result, i));
648
+ }
649
+
650
+
651
+ /*
652
+ * call-seq:
653
+ * res.getvalue( tup_num, field_num )
654
+ *
655
+ * Returns the value in tuple number _tup_num_, field _field_num_,
656
+ * or +nil+ if the field is +NULL+.
657
+ */
658
+ static VALUE
659
+ pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
660
+ {
661
+ t_pg_result *this = pgresult_get_this_safe(self);
662
+ int i = NUM2INT(tup_num);
663
+ int j = NUM2INT(field_num);
664
+
665
+ if(i < 0 || i >= PQntuples(this->pgresult)) {
666
+ rb_raise(rb_eArgError,"invalid tuple number %d", i);
667
+ }
668
+ if(j < 0 || j >= PQnfields(this->pgresult)) {
669
+ rb_raise(rb_eArgError,"invalid field number %d", j);
670
+ }
671
+ return this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, i, j);
672
+ }
673
+
674
+ /*
675
+ * call-seq:
676
+ * res.getisnull(tuple_position, field_position) -> boolean
677
+ *
678
+ * Returns +true+ if the specified value is +nil+; +false+ otherwise.
679
+ */
680
+ static VALUE
681
+ pgresult_getisnull(VALUE self, VALUE tup_num, VALUE field_num)
682
+ {
683
+ PGresult *result;
684
+ int i = NUM2INT(tup_num);
685
+ int j = NUM2INT(field_num);
686
+
687
+ result = pgresult_get(self);
688
+ if (i < 0 || i >= PQntuples(result)) {
689
+ rb_raise(rb_eArgError,"invalid tuple number %d", i);
690
+ }
691
+ if (j < 0 || j >= PQnfields(result)) {
692
+ rb_raise(rb_eArgError,"invalid field number %d", j);
693
+ }
694
+ return PQgetisnull(result, i, j) ? Qtrue : Qfalse;
695
+ }
696
+
697
+ /*
698
+ * call-seq:
699
+ * res.getlength( tup_num, field_num ) -> Fixnum
700
+ *
701
+ * Returns the (String) length of the field in bytes.
702
+ *
703
+ * Equivalent to <tt>res.value(<i>tup_num</i>,<i>field_num</i>).length</tt>.
704
+ */
705
+ static VALUE
706
+ pgresult_getlength(VALUE self, VALUE tup_num, VALUE field_num)
707
+ {
708
+ PGresult *result;
709
+ int i = NUM2INT(tup_num);
710
+ int j = NUM2INT(field_num);
711
+
712
+ result = pgresult_get(self);
713
+ if (i < 0 || i >= PQntuples(result)) {
714
+ rb_raise(rb_eArgError,"invalid tuple number %d", i);
715
+ }
716
+ if (j < 0 || j >= PQnfields(result)) {
717
+ rb_raise(rb_eArgError,"invalid field number %d", j);
718
+ }
719
+ return INT2FIX(PQgetlength(result, i, j));
720
+ }
721
+
722
+ /*
723
+ * call-seq:
724
+ * res.nparams() -> Fixnum
725
+ *
726
+ * Returns the number of parameters of a prepared statement.
727
+ * Only useful for the result returned by conn.describePrepared
728
+ */
729
+ static VALUE
730
+ pgresult_nparams(VALUE self)
731
+ {
732
+ PGresult *result;
733
+
734
+ result = pgresult_get(self);
735
+ return INT2FIX(PQnparams(result));
736
+ }
737
+
738
+ /*
739
+ * call-seq:
740
+ * res.paramtype( param_number ) -> Oid
741
+ *
742
+ * Returns the Oid of the data type of parameter _param_number_.
743
+ * Only useful for the result returned by conn.describePrepared
744
+ */
745
+ static VALUE
746
+ pgresult_paramtype(VALUE self, VALUE param_number)
747
+ {
748
+ PGresult *result;
749
+
750
+ result = pgresult_get(self);
751
+ return UINT2NUM(PQparamtype(result,NUM2INT(param_number)));
752
+ }
753
+
754
+ /*
755
+ * call-seq:
756
+ * res.cmd_status() -> String
757
+ *
758
+ * Returns the status string of the last query command.
759
+ */
760
+ static VALUE
761
+ pgresult_cmd_status(VALUE self)
762
+ {
763
+ VALUE ret = rb_tainted_str_new2(PQcmdStatus(pgresult_get(self)));
764
+ PG_ENCODING_SET_NOCHECK(ret, ENCODING_GET(self));
765
+ return ret;
766
+ }
767
+
768
+ /*
769
+ * call-seq:
770
+ * res.cmd_tuples() -> Integer
771
+ *
772
+ * Returns the number of tuples (rows) affected by the SQL command.
773
+ *
774
+ * If the SQL command that generated the PG::Result was not one of:
775
+ * * +INSERT+
776
+ * * +UPDATE+
777
+ * * +DELETE+
778
+ * * +MOVE+
779
+ * * +FETCH+
780
+ * or if no tuples were affected, <tt>0</tt> is returned.
781
+ */
782
+ static VALUE
783
+ pgresult_cmd_tuples(VALUE self)
784
+ {
785
+ long n;
786
+ n = strtol(PQcmdTuples(pgresult_get(self)),NULL, 10);
787
+ return INT2NUM(n);
788
+ }
789
+
790
+ /*
791
+ * call-seq:
792
+ * res.oid_value() -> Integer
793
+ *
794
+ * Returns the +oid+ of the inserted row if applicable,
795
+ * otherwise +nil+.
796
+ */
797
+ static VALUE
798
+ pgresult_oid_value(VALUE self)
799
+ {
800
+ Oid n = PQoidValue(pgresult_get(self));
801
+ if (n == InvalidOid)
802
+ return Qnil;
803
+ else
804
+ return UINT2NUM(n);
805
+ }
806
+
807
+ /* Utility methods not in libpq */
808
+
809
+ /*
810
+ * call-seq:
811
+ * res[ n ] -> Hash
812
+ *
813
+ * Returns tuple _n_ as a hash.
814
+ */
815
+ static VALUE
816
+ pgresult_aref(VALUE self, VALUE index)
817
+ {
818
+ t_pg_result *this = pgresult_get_this_safe(self);
819
+ int tuple_num = NUM2INT(index);
820
+ int field_num;
821
+ int num_tuples = PQntuples(this->pgresult);
822
+ VALUE tuple;
823
+
824
+ if( this->nfields == -1 )
825
+ pgresult_init_fnames( self );
826
+
827
+ if ( tuple_num < 0 || tuple_num >= num_tuples )
828
+ rb_raise( rb_eIndexError, "Index %d is out of range", tuple_num );
829
+
830
+ /* We reuse the Hash of the previous output for larger row counts.
831
+ * This is somewhat faster than populating an empty Hash object. */
832
+ tuple = NIL_P(this->tuple_hash) ? rb_hash_new() : this->tuple_hash;
833
+ for ( field_num = 0; field_num < this->nfields; field_num++ ) {
834
+ VALUE val = this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, tuple_num, field_num);
835
+ rb_hash_aset( tuple, this->fnames[field_num], val );
836
+ }
837
+ /* Store a copy of the filled hash for use at the next row. */
838
+ if( num_tuples > 10 )
839
+ this->tuple_hash = rb_hash_dup(tuple);
840
+
841
+ return tuple;
842
+ }
843
+
844
+ /*
845
+ * call-seq:
846
+ * res.each_row { |row| ... }
847
+ *
848
+ * Yields each row of the result. The row is a list of column values.
849
+ */
850
+ static VALUE
851
+ pgresult_each_row(VALUE self)
852
+ {
853
+ t_pg_result *this;
854
+ int row;
855
+ int field;
856
+ int num_rows;
857
+ int num_fields;
858
+
859
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, pgresult_ntuples_for_enum);
860
+
861
+ this = pgresult_get_this_safe(self);
862
+ num_rows = PQntuples(this->pgresult);
863
+ num_fields = PQnfields(this->pgresult);
864
+
865
+ for ( row = 0; row < num_rows; row++ ) {
866
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, num_fields, PG_MAX_COLUMNS)
867
+
868
+ /* populate the row */
869
+ for ( field = 0; field < num_fields; field++ ) {
870
+ row_values[field] = this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, row, field);
871
+ }
872
+ rb_yield( rb_ary_new4( num_fields, row_values ));
873
+ }
874
+
875
+ return Qnil;
876
+ }
877
+
878
+ /*
879
+ * call-seq:
880
+ * res.values -> Array
881
+ *
882
+ * Returns all tuples as an array of arrays.
883
+ */
884
+ static VALUE
885
+ pgresult_values(VALUE self)
886
+ {
887
+ t_pg_result *this = pgresult_get_this_safe(self);
888
+ int row;
889
+ int field;
890
+ int num_rows = PQntuples(this->pgresult);
891
+ int num_fields = PQnfields(this->pgresult);
892
+ VALUE results = rb_ary_new2( num_rows );
893
+
894
+ for ( row = 0; row < num_rows; row++ ) {
895
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, num_fields, PG_MAX_COLUMNS)
896
+
897
+ /* populate the row */
898
+ for ( field = 0; field < num_fields; field++ ) {
899
+ row_values[field] = this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, row, field);
900
+ }
901
+ rb_ary_store( results, row, rb_ary_new4( num_fields, row_values ) );
902
+ }
903
+
904
+ return results;
905
+ }
906
+
907
+ /*
908
+ * Make a Ruby array out of the encoded values from the specified
909
+ * column in the given result.
910
+ */
911
+ static VALUE
912
+ make_column_result_array( VALUE self, int col )
913
+ {
914
+ t_pg_result *this = pgresult_get_this_safe(self);
915
+ int rows = PQntuples( this->pgresult );
916
+ int i;
917
+ VALUE results = rb_ary_new2( rows );
918
+
919
+ if ( col >= PQnfields(this->pgresult) )
920
+ rb_raise( rb_eIndexError, "no column %d in result", col );
921
+
922
+ for ( i=0; i < rows; i++ ) {
923
+ VALUE val = this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, i, col);
924
+ rb_ary_store( results, i, val );
925
+ }
926
+
927
+ return results;
928
+ }
929
+
930
+
931
+ /*
932
+ * call-seq:
933
+ * res.column_values( n ) -> array
934
+ *
935
+ * Returns an Array of the values from the nth column of each
936
+ * tuple in the result.
937
+ *
938
+ */
939
+ static VALUE
940
+ pgresult_column_values(VALUE self, VALUE index)
941
+ {
942
+ int col = NUM2INT( index );
943
+ return make_column_result_array( self, col );
944
+ }
945
+
946
+
947
+ /*
948
+ * call-seq:
949
+ * res.field_values( field ) -> array
950
+ *
951
+ * Returns an Array of the values from the given _field_ of each tuple in the result.
952
+ *
953
+ */
954
+ static VALUE
955
+ pgresult_field_values( VALUE self, VALUE field )
956
+ {
957
+ PGresult *result = pgresult_get( self );
958
+ const char *fieldname = StringValueCStr( field );
959
+ int fnum = PQfnumber( result, fieldname );
960
+
961
+ if ( fnum < 0 )
962
+ rb_raise( rb_eIndexError, "no such field '%s' in result", fieldname );
963
+
964
+ return make_column_result_array( self, fnum );
965
+ }
966
+
967
+
968
+ /*
969
+ * call-seq:
970
+ * res.each{ |tuple| ... }
971
+ *
972
+ * Invokes block for each tuple in the result set.
973
+ */
974
+ static VALUE
975
+ pgresult_each(VALUE self)
976
+ {
977
+ PGresult *result;
978
+ int tuple_num;
979
+
980
+ RETURN_SIZED_ENUMERATOR(self, 0, NULL, pgresult_ntuples_for_enum);
981
+
982
+ result = pgresult_get(self);
983
+
984
+ for(tuple_num = 0; tuple_num < PQntuples(result); tuple_num++) {
985
+ rb_yield(pgresult_aref(self, INT2NUM(tuple_num)));
986
+ }
987
+ return self;
988
+ }
989
+
990
+ /*
991
+ * call-seq:
992
+ * res.fields() -> Array
993
+ *
994
+ * Returns an array of Strings representing the names of the fields in the result.
995
+ */
996
+ static VALUE
997
+ pgresult_fields(VALUE self)
998
+ {
999
+ t_pg_result *this = pgresult_get_this_safe(self);
1000
+
1001
+ if( this->nfields == -1 )
1002
+ pgresult_init_fnames( self );
1003
+
1004
+ return rb_ary_new4( this->nfields, this->fnames );
1005
+ }
1006
+
1007
+ /*
1008
+ * call-seq:
1009
+ * res.type_map = typemap
1010
+ *
1011
+ * Set the TypeMap that is used for type casts of result values to ruby objects.
1012
+ *
1013
+ * All value retrieval methods will respect the type map and will do the
1014
+ * type casts from PostgreSQL's wire format to Ruby objects on the fly,
1015
+ * according to the rules and decoders defined in the given typemap.
1016
+ *
1017
+ * +typemap+ must be a kind of PG::TypeMap .
1018
+ *
1019
+ */
1020
+ static VALUE
1021
+ pgresult_type_map_set(VALUE self, VALUE typemap)
1022
+ {
1023
+ t_pg_result *this = pgresult_get_this(self);
1024
+ t_typemap *p_typemap;
1025
+
1026
+ if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
1027
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1028
+ rb_obj_classname( typemap ) );
1029
+ }
1030
+ Data_Get_Struct(typemap, t_typemap, p_typemap);
1031
+
1032
+ this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
1033
+ this->p_typemap = DATA_PTR( this->typemap );
1034
+
1035
+ return typemap;
1036
+ }
1037
+
1038
+ /*
1039
+ * call-seq:
1040
+ * res.type_map -> value
1041
+ *
1042
+ * Returns the TypeMap that is currently set for type casts of result values to ruby objects.
1043
+ *
1044
+ */
1045
+ static VALUE
1046
+ pgresult_type_map_get(VALUE self)
1047
+ {
1048
+ t_pg_result *this = pgresult_get_this(self);
1049
+
1050
+ return this->typemap;
1051
+ }
1052
+
1053
+ #ifdef HAVE_PQSETSINGLEROWMODE
1054
+ /*
1055
+ * call-seq:
1056
+ * res.stream_each{ |tuple| ... }
1057
+ *
1058
+ * Invokes block for each tuple in the result set in single row mode.
1059
+ *
1060
+ * This is a convenience method for retrieving all result tuples
1061
+ * as they are transferred. It is an alternative to repeated calls of
1062
+ * PG::Connection#get_result , but given that it avoids the overhead of
1063
+ * wrapping each row into a dedicated result object, it delivers data in nearly
1064
+ * the same speed as with ordinary results.
1065
+ *
1066
+ * The result must be in status PGRES_SINGLE_TUPLE.
1067
+ * It iterates over all tuples until the status changes to PGRES_TUPLES_OK.
1068
+ * A PG::Error is raised for any errors from the server.
1069
+ *
1070
+ * Row description data does not change while the iteration. All value retrieval
1071
+ * methods refer to only the current row. Result#ntuples returns +1+ while
1072
+ * the iteration and +0+ after all tuples were yielded.
1073
+ *
1074
+ * Example:
1075
+ * conn.send_query( "first SQL query; second SQL query" )
1076
+ * conn.set_single_row_mode
1077
+ * conn.get_result.stream_each do |row|
1078
+ * # do something with the received row of the first query
1079
+ * end
1080
+ * conn.get_result.stream_each do |row|
1081
+ * # do something with the received row of the second query
1082
+ * end
1083
+ * conn.get_result # => nil (no more results)
1084
+ */
1085
+ static VALUE
1086
+ pgresult_stream_each(VALUE self)
1087
+ {
1088
+ t_pg_result *this;
1089
+ int nfields;
1090
+ PGconn *pgconn;
1091
+ PGresult *pgresult;
1092
+
1093
+ RETURN_ENUMERATOR(self, 0, NULL);
1094
+
1095
+ this = pgresult_get_this_safe(self);
1096
+ pgconn = pg_get_pgconn(this->connection);
1097
+ pgresult = this->pgresult;
1098
+ nfields = PQnfields(pgresult);
1099
+
1100
+ for(;;){
1101
+ int tuple_num;
1102
+ int ntuples = PQntuples(pgresult);
1103
+
1104
+ switch( PQresultStatus(pgresult) ){
1105
+ case PGRES_TUPLES_OK:
1106
+ if( ntuples == 0 )
1107
+ return self;
1108
+ rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
1109
+ case PGRES_SINGLE_TUPLE:
1110
+ break;
1111
+ default:
1112
+ pg_result_check( self );
1113
+ }
1114
+
1115
+ for(tuple_num = 0; tuple_num < ntuples; tuple_num++) {
1116
+ rb_yield(pgresult_aref(self, INT2NUM(tuple_num)));
1117
+ }
1118
+
1119
+ if( !this->autoclear ){
1120
+ PQclear( pgresult );
1121
+ this->pgresult = NULL;
1122
+ }
1123
+
1124
+ pgresult = gvl_PQgetResult(pgconn);
1125
+ if( pgresult == NULL )
1126
+ rb_raise( rb_eNoResultError, "no result received - possibly an intersection with another result retrieval");
1127
+
1128
+ if( nfields != PQnfields(pgresult) )
1129
+ rb_raise( rb_eInvalidChangeOfResultFields, "number of fields must not change in single row mode");
1130
+
1131
+ this->pgresult = pgresult;
1132
+ }
1133
+
1134
+ /* never reached */
1135
+ return self;
1136
+ }
1137
+
1138
+ /*
1139
+ * call-seq:
1140
+ * res.stream_each_row { |row| ... }
1141
+ *
1142
+ * Yields each row of the result set in single row mode.
1143
+ * The row is a list of column values.
1144
+ *
1145
+ * This method works equally to #stream_each , but yields an Array of
1146
+ * values.
1147
+ */
1148
+ static VALUE
1149
+ pgresult_stream_each_row(VALUE self)
1150
+ {
1151
+ t_pg_result *this;
1152
+ int row;
1153
+ int nfields;
1154
+ PGconn *pgconn;
1155
+ PGresult *pgresult;
1156
+
1157
+ RETURN_ENUMERATOR(self, 0, NULL);
1158
+
1159
+ this = pgresult_get_this_safe(self);
1160
+ pgconn = pg_get_pgconn(this->connection);
1161
+ pgresult = this->pgresult;
1162
+ nfields = PQnfields(pgresult);
1163
+
1164
+ for(;;){
1165
+ int ntuples = PQntuples(pgresult);
1166
+
1167
+ switch( PQresultStatus(pgresult) ){
1168
+ case PGRES_TUPLES_OK:
1169
+ if( ntuples == 0 )
1170
+ return self;
1171
+ rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
1172
+ case PGRES_SINGLE_TUPLE:
1173
+ break;
1174
+ default:
1175
+ pg_result_check( self );
1176
+ }
1177
+
1178
+ for ( row = 0; row < ntuples; row++ ) {
1179
+ PG_VARIABLE_LENGTH_ARRAY(VALUE, row_values, nfields, PG_MAX_COLUMNS)
1180
+ int field;
1181
+
1182
+ /* populate the row */
1183
+ for ( field = 0; field < nfields; field++ ) {
1184
+ row_values[field] = this->p_typemap->funcs.typecast_result_value(this->p_typemap, self, row, field);
1185
+ }
1186
+ rb_yield( rb_ary_new4( nfields, row_values ));
1187
+ }
1188
+
1189
+ if( !this->autoclear ){
1190
+ PQclear( pgresult );
1191
+ this->pgresult = NULL;
1192
+ }
1193
+
1194
+ pgresult = gvl_PQgetResult(pgconn);
1195
+ if( pgresult == NULL )
1196
+ rb_raise( rb_eNoResultError, "no result received - possibly an intersection with another result retrieval");
1197
+
1198
+ if( nfields != PQnfields(pgresult) )
1199
+ rb_raise( rb_eInvalidChangeOfResultFields, "number of fields must not change in single row mode");
1200
+
1201
+ this->pgresult = pgresult;
1202
+ }
1203
+
1204
+ /* never reached */
1205
+ return self;
1206
+ }
1207
+ #endif
1208
+
1209
+
1210
+ void
1211
+ init_pg_result()
1212
+ {
1213
+ rb_cPGresult = rb_define_class_under( rb_mPG, "Result", rb_cObject );
1214
+ rb_define_alloc_func( rb_cPGresult, pgresult_s_allocate );
1215
+ rb_include_module(rb_cPGresult, rb_mEnumerable);
1216
+ rb_include_module(rb_cPGresult, rb_mPGconstants);
1217
+
1218
+ /****** PG::Result INSTANCE METHODS: libpq ******/
1219
+ rb_define_method(rb_cPGresult, "result_status", pgresult_result_status, 0);
1220
+ rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, 1);
1221
+ rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
1222
+ rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
1223
+ rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
1224
+ rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
1225
+ rb_define_method(rb_cPGresult, "clear", pg_result_clear, 0);
1226
+ rb_define_method(rb_cPGresult, "check", pg_result_check, 0);
1227
+ rb_define_alias (rb_cPGresult, "check_result", "check");
1228
+ rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
1229
+ rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");
1230
+ rb_define_method(rb_cPGresult, "nfields", pgresult_nfields, 0);
1231
+ rb_define_alias(rb_cPGresult, "num_fields", "nfields");
1232
+ rb_define_method(rb_cPGresult, "fname", pgresult_fname, 1);
1233
+ rb_define_method(rb_cPGresult, "fnumber", pgresult_fnumber, 1);
1234
+ rb_define_method(rb_cPGresult, "ftable", pgresult_ftable, 1);
1235
+ rb_define_method(rb_cPGresult, "ftablecol", pgresult_ftablecol, 1);
1236
+ rb_define_method(rb_cPGresult, "fformat", pgresult_fformat, 1);
1237
+ rb_define_method(rb_cPGresult, "ftype", pgresult_ftype, 1);
1238
+ rb_define_method(rb_cPGresult, "fmod", pgresult_fmod, 1);
1239
+ rb_define_method(rb_cPGresult, "fsize", pgresult_fsize, 1);
1240
+ rb_define_method(rb_cPGresult, "getvalue", pgresult_getvalue, 2);
1241
+ rb_define_method(rb_cPGresult, "getisnull", pgresult_getisnull, 2);
1242
+ rb_define_method(rb_cPGresult, "getlength", pgresult_getlength, 2);
1243
+ rb_define_method(rb_cPGresult, "nparams", pgresult_nparams, 0);
1244
+ rb_define_method(rb_cPGresult, "paramtype", pgresult_paramtype, 1);
1245
+ rb_define_method(rb_cPGresult, "cmd_status", pgresult_cmd_status, 0);
1246
+ rb_define_method(rb_cPGresult, "cmd_tuples", pgresult_cmd_tuples, 0);
1247
+ rb_define_alias(rb_cPGresult, "cmdtuples", "cmd_tuples");
1248
+ rb_define_method(rb_cPGresult, "oid_value", pgresult_oid_value, 0);
1249
+
1250
+ /****** PG::Result INSTANCE METHODS: other ******/
1251
+ rb_define_method(rb_cPGresult, "[]", pgresult_aref, 1);
1252
+ rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
1253
+ rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
1254
+ rb_define_method(rb_cPGresult, "each_row", pgresult_each_row, 0);
1255
+ rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
1256
+ rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
1257
+ rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);
1258
+ rb_define_method(rb_cPGresult, "cleared?", pgresult_cleared_p, 0);
1259
+ rb_define_method(rb_cPGresult, "autoclear?", pgresult_autoclear_p, 0);
1260
+
1261
+ rb_define_method(rb_cPGresult, "type_map=", pgresult_type_map_set, 1);
1262
+ rb_define_method(rb_cPGresult, "type_map", pgresult_type_map_get, 0);
1263
+
1264
+ #ifdef HAVE_PQSETSINGLEROWMODE
1265
+ /****** PG::Result INSTANCE METHODS: streaming ******/
1266
+ rb_define_method(rb_cPGresult, "stream_each", pgresult_stream_each, 0);
1267
+ rb_define_method(rb_cPGresult, "stream_each_row", pgresult_stream_each_row, 0);
1268
+ #endif
1269
+ }
1270
+
1271
+