rdo-postgres 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +33 -11
- data/ext/rdo_postgres/arrays.c +48 -0
- data/ext/rdo_postgres/arrays.h +9 -0
- data/ext/rdo_postgres/casts.c +68 -25
- data/ext/rdo_postgres/casts.h +3 -0
- data/ext/rdo_postgres/driver.c +4 -8
- data/ext/rdo_postgres/extconf.rb +1 -2
- data/ext/rdo_postgres/rdo_postgres.c +2 -0
- data/ext/rdo_postgres/statements.c +25 -20
- data/ext/rdo_postgres/types.h +74 -0
- data/lib/rdo/postgres.rb +12 -0
- data/lib/rdo/postgres/array.rb +84 -0
- data/lib/rdo/postgres/array/boolean.rb +21 -0
- data/lib/rdo/postgres/array/bytea.rb +22 -0
- data/lib/rdo/postgres/array/date.rb +17 -0
- data/lib/rdo/postgres/array/float.rb +30 -0
- data/lib/rdo/postgres/array/integer.rb +21 -0
- data/lib/rdo/postgres/array/numeric.rb +23 -0
- data/lib/rdo/postgres/array/text.rb +15 -0
- data/lib/rdo/postgres/array/timestamp.rb +17 -0
- data/lib/rdo/postgres/array/timestamp_tz.rb +17 -0
- data/lib/rdo/postgres/version.rb +1 -1
- data/spec/postgres/array/boolean_spec.rb +74 -0
- data/spec/postgres/array/bytea_spec.rb +82 -0
- data/spec/postgres/array/date_spec.rb +74 -0
- data/spec/postgres/array/float_spec.rb +98 -0
- data/spec/postgres/array/integer_spec.rb +74 -0
- data/spec/postgres/array/numeric_spec.rb +83 -0
- data/spec/postgres/array/timestamp_spec.rb +80 -0
- data/spec/postgres/array/timestamp_tz_spec.rb +80 -0
- data/spec/postgres/array_spec.rb +122 -0
- data/spec/postgres/bind_params_spec.rb +191 -1
- data/spec/postgres/type_cast_spec.rb +223 -0
- metadata +33 -2
data/README.md
CHANGED
@@ -8,9 +8,8 @@ This is the PostgreSQL driver for [RDO—Ruby Data Objects]
|
|
8
8
|
Refer to the RDO project [README](https://github.com/d11wtq/rdo) for usage
|
9
9
|
information.
|
10
10
|
|
11
|
-
This driver cannot be used with
|
12
|
-
|
13
|
-
features.
|
11
|
+
This driver cannot be used with PostgreSQL versions older than 7.4. Those
|
12
|
+
versions are no longer supported by PostgreSQL in any case.
|
14
13
|
|
15
14
|
## Installation
|
16
15
|
|
@@ -51,6 +50,33 @@ conn = RDO.connect(
|
|
51
50
|
)
|
52
51
|
```
|
53
52
|
|
53
|
+
### Type Support
|
54
|
+
|
55
|
+
If not listed below, the String form of the value will be returned. The
|
56
|
+
currently mapped types are:
|
57
|
+
|
58
|
+
- NULL -> nil
|
59
|
+
- BOOLEAN -> TrueClass/FalseClass
|
60
|
+
- TEXT -> String
|
61
|
+
- VARCHAR -> String
|
62
|
+
- CHAR -> String
|
63
|
+
- BYTEA -> String
|
64
|
+
- INTEGER -> Fixnum
|
65
|
+
- INT2 -> Fixnum
|
66
|
+
- INT4 -> Fixnum
|
67
|
+
- INT8 -> Fixnum
|
68
|
+
- FLOAT/REAL -> Float
|
69
|
+
- FLOAT4 -> Float
|
70
|
+
- FLOAT8 -> Float
|
71
|
+
- NUMERIC/DECIMAL -> BigDecimal
|
72
|
+
- DATE -> Date
|
73
|
+
- TIMESTAMP -> DateTime (in the system time zone)
|
74
|
+
- TIMESTAMPTZ -> DateTime (in the specified time zone)
|
75
|
+
|
76
|
+
All 1-dimensional Arrays of the above listed are also available. Support for
|
77
|
+
multi-dimensional Arrays is planned immediately. Support for custom-typed
|
78
|
+
Arrays is coming.
|
79
|
+
|
54
80
|
### Bind parameters support
|
55
81
|
|
56
82
|
PostgreSQL uses $1, $2 etc for bind parameters. RDO uses '?'. You can use
|
@@ -72,17 +98,13 @@ conn.execute("SELECT * FROM users WHERE banned = $1 AND created_at > ?", true, 1
|
|
72
98
|
|
73
99
|
## Contributing
|
74
100
|
|
75
|
-
Contributions to support older versions of PostgreSQL (< 7.4) welcomed,
|
76
|
-
though if the changes required break the native support for newer versions
|
77
|
-
pull requests will not be accepted. It is possible to write a separate
|
78
|
-
driver for older versions of PostgreSQL and register it under the driver
|
79
|
-
name 'postgresql' instead of this one if that is preferable. Alternatively,
|
80
|
-
use an explicit name that indicates legacy compatibility, such as
|
81
|
-
'postgres73'.
|
82
|
-
|
83
101
|
If you find any bugs, please send a pull request if you think you can
|
84
102
|
fix it, or file in an issue in the issue tracker.
|
85
103
|
|
104
|
+
I'm particulary interested in patches surrounding support for built-in type
|
105
|
+
arrays, multi-dimensional arrays and arrays of custom types, such as ENUMs
|
106
|
+
(in order of difficulty/preference).
|
107
|
+
|
86
108
|
When sending pull requests, please use topic branches—don't send a pull
|
87
109
|
request from the master branch of your fork, as that may change
|
88
110
|
unintentionally.
|
@@ -0,0 +1,48 @@
|
|
1
|
+
/*
|
2
|
+
* RDO Postgres Driver.
|
3
|
+
* Copyright © 2012 Chris Corbyn.
|
4
|
+
*
|
5
|
+
* See LICENSE file for details.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "arrays.h"
|
9
|
+
#include "casts.h"
|
10
|
+
#include "macros.h"
|
11
|
+
#include <ruby.h>
|
12
|
+
#include <libpq-fe.h>
|
13
|
+
|
14
|
+
/** Parse a bytea string into a binary Ruby String */
|
15
|
+
static VALUE rdo_postgres_array_bytea_parse_value(VALUE self, VALUE s) {
|
16
|
+
s = rb_call_super(1, &s);
|
17
|
+
Check_Type(s, T_STRING);
|
18
|
+
return rdo_postgres_cast_bytea(RSTRING_PTR(s), RSTRING_LEN(s));
|
19
|
+
}
|
20
|
+
|
21
|
+
/** Format a value as a bytea */
|
22
|
+
static VALUE rdo_postgres_array_bytea_format_value(VALUE self, VALUE v) {
|
23
|
+
if (TYPE(v) != T_STRING) {
|
24
|
+
v = RDO_OBJ_TO_S(v);
|
25
|
+
}
|
26
|
+
|
27
|
+
size_t len = 0;
|
28
|
+
unsigned char * bytea = PQescapeBytea((unsigned char *) RSTRING_PTR(v),
|
29
|
+
RSTRING_LEN(v), &len);
|
30
|
+
|
31
|
+
VALUE escaped = rb_str_new((char *) bytea, len - 1);
|
32
|
+
VALUE formatted = rb_call_super(1, &escaped);
|
33
|
+
|
34
|
+
PQfreemem(bytea);
|
35
|
+
|
36
|
+
return formatted;
|
37
|
+
}
|
38
|
+
|
39
|
+
/** Initialize Array extensions */
|
40
|
+
void Init_rdo_postgres_arrays(void) {
|
41
|
+
VALUE cByteaArray = rb_path2class("RDO::Postgres::Array::Bytea");
|
42
|
+
|
43
|
+
rb_define_method(cByteaArray,
|
44
|
+
"parse_value", rdo_postgres_array_bytea_parse_value, 1);
|
45
|
+
|
46
|
+
rb_define_method(cByteaArray,
|
47
|
+
"format_value", rdo_postgres_array_bytea_format_value, 1);
|
48
|
+
}
|
data/ext/rdo_postgres/casts.c
CHANGED
@@ -7,13 +7,18 @@
|
|
7
7
|
|
8
8
|
#include "casts.h"
|
9
9
|
#include <stdlib.h>
|
10
|
-
#include <postgres.h>
|
11
|
-
#include <catalog/pg_type.h>
|
12
10
|
#include "macros.h"
|
11
|
+
#include "types.h"
|
13
12
|
|
14
13
|
/** Predicate test if the given string is formatted as \x0afe... */
|
15
14
|
#define RDO_PG_NEW_HEX_P(s, len) (len >= 2 && s[0] == '\\' && s[1] == 'x')
|
16
15
|
|
16
|
+
/** Parse a PostgreSQL array and return an Array for the given type */
|
17
|
+
#define RDO_PG_ARRAY(clsname, s, len) \
|
18
|
+
(rb_funcall((rb_funcall(rb_path2class("RDO::Postgres::Array::" clsname), \
|
19
|
+
rb_intern("parse"), 1, rb_str_new(s, len))), \
|
20
|
+
rb_intern("to_a"), 0))
|
21
|
+
|
17
22
|
/** Lookup table for fast conversion of bytea hex strings to binary data */
|
18
23
|
static char * RDOPostgres_HexLookup;
|
19
24
|
|
@@ -45,19 +50,27 @@ static VALUE rdo_postgres_cast_bytea_hex(char * hex, size_t len) {
|
|
45
50
|
|
46
51
|
/** Cast from a bytea to a String according to a regular escape format */
|
47
52
|
static VALUE rdo_postgres_cast_bytea_escape(char * escaped, size_t len) {
|
48
|
-
unsigned char * buffer = PQunescapeBytea(escaped, &len);
|
53
|
+
unsigned char * buffer = PQunescapeBytea((unsigned char *) escaped, &len);
|
49
54
|
|
50
55
|
if (buffer == NULL) {
|
51
56
|
rb_raise(rb_eRuntimeError,
|
52
57
|
"Failed to allocate memory for PQunescapeBytea() conversion");
|
53
58
|
}
|
54
59
|
|
55
|
-
VALUE str = rb_str_new(buffer, len);
|
60
|
+
VALUE str = rb_str_new((char *) buffer, len);
|
56
61
|
PQfreemem(buffer);
|
57
62
|
|
58
63
|
return str;
|
59
64
|
}
|
60
65
|
|
66
|
+
/** Cast from a bytea to a String, automatically detecting the format */
|
67
|
+
VALUE rdo_postgres_cast_bytea(char * escaped, size_t len) {
|
68
|
+
if (RDO_PG_NEW_HEX_P(escaped, len))
|
69
|
+
return rdo_postgres_cast_bytea_hex(escaped, len);
|
70
|
+
else
|
71
|
+
return rdo_postgres_cast_bytea_escape(escaped, len);
|
72
|
+
}
|
73
|
+
|
61
74
|
/** Get the value as a ruby type */
|
62
75
|
VALUE rdo_postgres_cast_value(PGresult * res, int row, int col, int enc) {
|
63
76
|
if (PQgetisnull(res, row, col)) {
|
@@ -68,42 +81,72 @@ VALUE rdo_postgres_cast_value(PGresult * res, int row, int col, int enc) {
|
|
68
81
|
int length = PQgetlength(res, row, col);
|
69
82
|
|
70
83
|
switch (PQftype(res, col)) {
|
71
|
-
case
|
72
|
-
case
|
73
|
-
case
|
84
|
+
case RDO_PG_INT2OID:
|
85
|
+
case RDO_PG_INT4OID:
|
86
|
+
case RDO_PG_INT8OID:
|
74
87
|
return RDO_FIXNUM(value);
|
75
88
|
|
76
|
-
case
|
77
|
-
case
|
89
|
+
case RDO_PG_FLOAT4OID:
|
90
|
+
case RDO_PG_FLOAT8OID:
|
78
91
|
return RDO_FLOAT(value);
|
79
92
|
|
80
|
-
case
|
93
|
+
case RDO_PG_NUMERICOID:
|
81
94
|
return RDO_DECIMAL(value);
|
82
95
|
|
83
|
-
case
|
96
|
+
case RDO_PG_BOOLOID:
|
84
97
|
return RDO_BOOL(value);
|
85
98
|
|
86
|
-
case
|
87
|
-
|
88
|
-
return rdo_postgres_cast_bytea_hex(value, length);
|
89
|
-
else
|
90
|
-
return rdo_postgres_cast_bytea_escape(value, length);
|
99
|
+
case RDO_PG_BYTEAOID:
|
100
|
+
return rdo_postgres_cast_bytea(value, length);
|
91
101
|
|
92
|
-
case
|
102
|
+
case RDO_PG_DATEOID:
|
93
103
|
return RDO_DATE(value);
|
94
104
|
|
95
|
-
case
|
105
|
+
case RDO_PG_TIMESTAMPOID:
|
96
106
|
return RDO_DATE_TIME_WITHOUT_ZONE(value);
|
97
107
|
|
98
|
-
case
|
108
|
+
case RDO_PG_TIMESTAMPTZOID:
|
99
109
|
return RDO_DATE_TIME_WITH_ZONE(value);
|
100
110
|
|
101
|
-
case
|
102
|
-
case
|
103
|
-
case
|
104
|
-
case
|
111
|
+
case RDO_PG_TEXTOID:
|
112
|
+
case RDO_PG_CHAROID:
|
113
|
+
case RDO_PG_VARCHAROID:
|
114
|
+
case RDO_PG_BPCHAROID:
|
105
115
|
return RDO_STRING(value, length, enc);
|
106
116
|
|
117
|
+
case RDO_PG_TEXTARRAYOID:
|
118
|
+
case RDO_PG_CHARARRAYOID:
|
119
|
+
case RDO_PG_BPCHARARRAYOID:
|
120
|
+
case RDO_PG_VARCHARARRAYOID:
|
121
|
+
return RDO_PG_ARRAY("Text", value, length);
|
122
|
+
|
123
|
+
case RDO_PG_INT2ARRAYOID:
|
124
|
+
case RDO_PG_INT4ARRAYOID:
|
125
|
+
case RDO_PG_INT8ARRAYOID:
|
126
|
+
return RDO_PG_ARRAY("Integer", value, length);
|
127
|
+
|
128
|
+
case RDO_PG_FLOAT4ARRAYOID:
|
129
|
+
case RDO_PG_FLOAT8ARRAYOID:
|
130
|
+
return RDO_PG_ARRAY("Float", value, length);
|
131
|
+
|
132
|
+
case RDO_PG_NUMERICARRAYOID:
|
133
|
+
return RDO_PG_ARRAY("Numeric", value, length);
|
134
|
+
|
135
|
+
case RDO_PG_BOOLARRAYOID:
|
136
|
+
return RDO_PG_ARRAY("Boolean", value, length);
|
137
|
+
|
138
|
+
case RDO_PG_BYTEAARRAYOID:
|
139
|
+
return RDO_PG_ARRAY("Bytea", value, length);
|
140
|
+
|
141
|
+
case RDO_PG_DATEARRAYOID:
|
142
|
+
return RDO_PG_ARRAY("Date", value, length);
|
143
|
+
|
144
|
+
case RDO_PG_TIMESTAMPARRAYOID:
|
145
|
+
return RDO_PG_ARRAY("Timestamp", value, length);
|
146
|
+
|
147
|
+
case RDO_PG_TIMESTAMPTZARRAYOID:
|
148
|
+
return RDO_PG_ARRAY("TimestampTZ", value, length);
|
149
|
+
|
107
150
|
default:
|
108
151
|
return RDO_BINARY_STRING(value, length);
|
109
152
|
}
|
@@ -111,11 +154,11 @@ VALUE rdo_postgres_cast_value(PGresult * res, int row, int col, int enc) {
|
|
111
154
|
|
112
155
|
/* Initialize hex decoding lookup table */
|
113
156
|
void Init_rdo_postgres_casts(void) {
|
114
|
-
RDOPostgres_HexLookup = malloc(sizeof(char) *
|
157
|
+
RDOPostgres_HexLookup = malloc(sizeof(char) * 256);
|
115
158
|
|
116
159
|
if (RDOPostgres_HexLookup == NULL) {
|
117
160
|
rb_raise(rb_eRuntimeError,
|
118
|
-
"Failed to allocate
|
161
|
+
"Failed to allocate 256 bytes for internal lookup table");
|
119
162
|
}
|
120
163
|
|
121
164
|
char c;
|
data/ext/rdo_postgres/casts.h
CHANGED
@@ -12,5 +12,8 @@
|
|
12
12
|
/** Cast the given value from the result to a ruby type */
|
13
13
|
VALUE rdo_postgres_cast_value(PGresult * res, int row, int col, int enc);
|
14
14
|
|
15
|
+
/** Special case for casting a bytea value */
|
16
|
+
VALUE rdo_postgres_cast_bytea(char * escaped, size_t len);
|
17
|
+
|
15
18
|
/** Initialize the casting framework */
|
16
19
|
void Init_rdo_postgres_casts(void);
|
data/ext/rdo_postgres/driver.c
CHANGED
@@ -49,12 +49,10 @@ static VALUE rdo_postgres_driver_open(VALUE self) {
|
|
49
49
|
RSTRING_PTR(rb_funcall(self, rb_intern("connect_db_string"), 0)));
|
50
50
|
|
51
51
|
if (driver->conn_ptr == NULL || PQstatus(driver->conn_ptr) == CONNECTION_BAD) {
|
52
|
-
|
53
|
-
"PostgreSQL connection failed: %s",
|
52
|
+
RDO_ERROR("PostgreSQL connection failed: %s",
|
54
53
|
PQerrorMessage(driver->conn_ptr));
|
55
54
|
} else if (PQprotocolVersion(driver->conn_ptr) < 3) {
|
56
|
-
|
57
|
-
"rdo-postgres requires PostgreSQL protocol version >= 3 (using %u). "
|
55
|
+
RDO_ERROR("rdo-postgres requires PostgreSQL protocol version >= 3 (using %u). "
|
58
56
|
"PostgreSQL >= 7.4 required.",
|
59
57
|
PQprotocolVersion(driver->conn_ptr));
|
60
58
|
} else {
|
@@ -98,8 +96,7 @@ static VALUE rdo_postgres_driver_prepare(VALUE self, VALUE cmd) {
|
|
98
96
|
Data_Get_Struct(self, RDOPostgresDriver, driver);
|
99
97
|
|
100
98
|
if (!(driver->is_open)) {
|
101
|
-
|
102
|
-
"Unable to prepare statement: connection is not open");
|
99
|
+
RDO_ERROR("Unable to prepare statement: connection is not open");
|
103
100
|
}
|
104
101
|
|
105
102
|
char name[32];
|
@@ -120,8 +117,7 @@ static VALUE rdo_postgres_driver_quote(VALUE self, VALUE str) {
|
|
120
117
|
Data_Get_Struct(self, RDOPostgresDriver, driver);
|
121
118
|
|
122
119
|
if (!(driver->is_open)) {
|
123
|
-
|
124
|
-
"Unable to quote string: connection is not open");
|
120
|
+
RDO_ERROR("Unable to quote string: connection is not open");
|
125
121
|
}
|
126
122
|
|
127
123
|
char * quoted = malloc(sizeof(char) * RSTRING_LEN(str) * 2 + 1);
|
data/ext/rdo_postgres/extconf.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include <stdlib.h>
|
9
9
|
#include <ruby.h>
|
10
10
|
#include "driver.h"
|
11
|
+
#include "arrays.h"
|
11
12
|
|
12
13
|
/**
|
13
14
|
* Extension initializer.
|
@@ -15,4 +16,5 @@
|
|
15
16
|
void Init_rdo_postgres(void) {
|
16
17
|
rb_require("rdo");
|
17
18
|
Init_rdo_postgres_driver();
|
19
|
+
Init_rdo_postgres_arrays();
|
18
20
|
}
|
@@ -12,8 +12,7 @@
|
|
12
12
|
#include "macros.h"
|
13
13
|
#include <stdlib.h>
|
14
14
|
#include <libpq-fe.h>
|
15
|
-
#include
|
16
|
-
#include <catalog/pg_type.h>
|
15
|
+
#include "types.h"
|
17
16
|
|
18
17
|
/** I don't like magic numbers */
|
19
18
|
#define RDO_PG_NO_OIDS 0
|
@@ -21,6 +20,11 @@
|
|
21
20
|
#define RDO_PG_TEXT_INPUT NULL
|
22
21
|
#define RDO_PG_TEXT_OUTPUT 0
|
23
22
|
|
23
|
+
/** Wrap a Ruby Array with a RDO::Postgres::Array */
|
24
|
+
#define RDO_PG_WRAP_ARRAY(clsname, a) \
|
25
|
+
(rb_funcall(rb_path2class("RDO::Postgres::Array::" clsname), \
|
26
|
+
rb_intern("new"), 1, a))
|
27
|
+
|
24
28
|
/** RDO::Postgres::StatementExecutor */
|
25
29
|
static VALUE rdo_postgres_cStatementExecutor;
|
26
30
|
|
@@ -60,8 +64,7 @@ static void rdo_postgres_statement_executor_prepare(VALUE self) {
|
|
60
64
|
Data_Get_Struct(self, RDOPostgresStatementExecutor, executor);
|
61
65
|
|
62
66
|
if (!(executor->driver->is_open)) {
|
63
|
-
|
64
|
-
"Unable to prepare statement: connection is not open");
|
67
|
+
RDO_ERROR("Unable to prepare statement: connection is not open");
|
65
68
|
}
|
66
69
|
|
67
70
|
char * cmd = rdo_postgres_params_inject_markers(executor->cmd);
|
@@ -85,8 +88,7 @@ static void rdo_postgres_statement_executor_prepare(VALUE self) {
|
|
85
88
|
char msg[sizeof(char) * (strlen(PQresultErrorMessage(res)) + 1)];
|
86
89
|
strcpy(msg, PQresultErrorMessage(res));
|
87
90
|
PQclear(res);
|
88
|
-
|
89
|
-
"Failed to prepare statement: %s", msg);
|
91
|
+
RDO_ERROR("Failed to prepare statement: %s", msg);
|
90
92
|
}
|
91
93
|
|
92
94
|
res = PQdescribePrepared(executor->driver->conn_ptr, executor->stmt_name);
|
@@ -95,8 +97,7 @@ static void rdo_postgres_statement_executor_prepare(VALUE self) {
|
|
95
97
|
char msg[sizeof(char) * (strlen(PQresultErrorMessage(res)) + 1)];
|
96
98
|
strcpy(msg, PQresultErrorMessage(res));
|
97
99
|
PQclear(res);
|
98
|
-
|
99
|
-
"Failed to prepare statement: %s", msg);
|
100
|
+
RDO_ERROR("Failed to prepare statement: %s", msg);
|
100
101
|
}
|
101
102
|
|
102
103
|
executor->nparams = PQnparams(res);
|
@@ -154,12 +155,11 @@ static VALUE rdo_postgres_statement_executor_execute(int argc, VALUE * args,
|
|
154
155
|
Data_Get_Struct(self, RDOPostgresStatementExecutor, executor);
|
155
156
|
|
156
157
|
if (!(executor->driver->is_open)) {
|
157
|
-
|
158
|
-
"Unable to execute statement: connection is not open");
|
158
|
+
RDO_ERROR("Unable to execute statement: connection is not open");
|
159
159
|
}
|
160
160
|
|
161
161
|
if (argc != executor->nparams) {
|
162
|
-
rb_raise(
|
162
|
+
rb_raise(rb_eArgError,
|
163
163
|
"Bind parameter count mismatch: wanted %i, got %i",
|
164
164
|
executor->nparams, argc);
|
165
165
|
}
|
@@ -173,13 +173,21 @@ static VALUE rdo_postgres_statement_executor_execute(int argc, VALUE * args,
|
|
173
173
|
values[i] = NULL;
|
174
174
|
lengths[i] = 0;
|
175
175
|
} else {
|
176
|
+
if (TYPE(args[i]) == T_ARRAY) {
|
177
|
+
if (executor->param_types[i] == RDO_PG_BYTEAARRAYOID) {
|
178
|
+
args[i] = RDO_PG_WRAP_ARRAY("Bytea", args[i]);
|
179
|
+
} else {
|
180
|
+
args[i] = RDO_PG_WRAP_ARRAY("Text", args[i]);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
176
184
|
if (TYPE(args[i]) != T_STRING) {
|
177
185
|
args[i] = RDO_OBJ_TO_S(args[i]);
|
178
186
|
}
|
179
187
|
|
180
|
-
if (executor->param_types[i] ==
|
181
|
-
values[i] = PQescapeByteaConn(executor->driver->conn_ptr,
|
182
|
-
RSTRING_PTR(args[i]),
|
188
|
+
if (executor->param_types[i] == RDO_PG_BYTEAOID) {
|
189
|
+
values[i] = (char *) PQescapeByteaConn(executor->driver->conn_ptr,
|
190
|
+
(unsigned char *) RSTRING_PTR(args[i]),
|
183
191
|
RSTRING_LEN(args[i]),
|
184
192
|
&(lengths[i]));
|
185
193
|
} else {
|
@@ -199,7 +207,7 @@ static VALUE rdo_postgres_statement_executor_execute(int argc, VALUE * args,
|
|
199
207
|
RDO_PG_TEXT_OUTPUT);
|
200
208
|
|
201
209
|
for (i = 0; i < argc; ++i) {
|
202
|
-
if (executor->param_types[i] ==
|
210
|
+
if (executor->param_types[i] == RDO_PG_BYTEAOID) {
|
203
211
|
PQfreemem(values[i]);
|
204
212
|
}
|
205
213
|
}
|
@@ -208,13 +216,10 @@ static VALUE rdo_postgres_statement_executor_execute(int argc, VALUE * args,
|
|
208
216
|
|
209
217
|
if (status == PGRES_BAD_RESPONSE || status == PGRES_FATAL_ERROR) {
|
210
218
|
PQclear(res);
|
211
|
-
|
212
|
-
"Failed to execute statement: %s", PQresultErrorMessage(res));
|
219
|
+
RDO_ERROR("Failed to execute statement: %s", PQresultErrorMessage(res));
|
213
220
|
}
|
214
221
|
|
215
|
-
return
|
216
|
-
rb_intern("new"), 2,
|
217
|
-
rdo_postgres_tuple_list_new(res, executor->driver->encoding),
|
222
|
+
return RDO_RESULT(rdo_postgres_tuple_list_new(res, executor->driver->encoding),
|
218
223
|
rdo_postgres_result_info_new(res));
|
219
224
|
}
|
220
225
|
|