rdo 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/.travis.yml +7 -0
- data/README.md +19 -7
- data/Rakefile +13 -1
- data/ext/rdo/extconf.rb +7 -0
- data/ext/rdo/rdo.c +175 -0
- data/lib/rdo.rb +3 -0
- data/lib/rdo/driver.rb +30 -0
- data/lib/rdo/version.rb +1 -1
- data/rdo.gemspec +2 -1
- data/spec/rdo/driver_spec.rb +96 -0
- data/spec/support/driver_with_backwards_quote.rb +29 -0
- data/spec/support/driver_with_everything.rb +2 -1
- data/spec/support/driver_without_statements.rb +2 -1
- metadata +33 -12
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -6,7 +6,9 @@ interface. Where a feature is not natively supported by the DBMS—for example,
|
|
6
6
|
prepared statements—it is seamlessly emulated, so you don't need to code
|
7
7
|
around it.
|
8
8
|
|
9
|
-
It targets **Ruby
|
9
|
+
It targets **Ruby 1.9** and newer.
|
10
|
+
|
11
|
+
[](http://travis-ci.org/d11wtq/rdo)
|
10
12
|
|
11
13
|
``` ruby
|
12
14
|
require "rdo"
|
@@ -103,21 +105,27 @@ And then execute:
|
|
103
105
|
<td>sqlite, sqlite3</td>
|
104
106
|
<td><a href="https://github.com/d11wtq/rdo-sqlite">rdo-sqlite</a></td>
|
105
107
|
<td><a href="https://github.com/d11wtq">d11wtq</a></td>
|
106
|
-
<td>
|
108
|
+
<td>
|
109
|
+
<img src="https://secure.travis-ci.org/d11wtq/rdo-sqlite.png?branch=master"
|
110
|
+
alt="Build Status" title="Build Status" />
|
111
|
+
</td>
|
107
112
|
</tr>
|
108
113
|
<tr>
|
109
114
|
<th>PostgreSQL</th>
|
110
115
|
<td>postgresql, postgres</td>
|
111
116
|
<td><a href="https://github.com/d11wtq/rdo-postgres">rdo-postgres</a></td>
|
112
117
|
<td><a href="https://github.com/d11wtq">d11wtq</a></td>
|
113
|
-
<td>
|
118
|
+
<td>
|
119
|
+
<img src="https://secure.travis-ci.org/d11wtq/rdo-postgres.png?branch=master"
|
120
|
+
alt="Build Status" title="Build Status" />
|
121
|
+
</td>
|
114
122
|
</tr>
|
115
123
|
<tr>
|
116
124
|
<th>MySQL</th>
|
117
125
|
<td>mysql</td>
|
118
126
|
<td><a href="https://github.com/d11wtq/rdo-mysql">rdo-mysql</a></td>
|
119
127
|
<td><a href="https://github.com/d11wtq">d11wtq</a></td>
|
120
|
-
<td>
|
128
|
+
<td>In development</td>
|
121
129
|
</tr>
|
122
130
|
</tbody>
|
123
131
|
</table>
|
@@ -165,7 +173,7 @@ p conn.open? #=> true
|
|
165
173
|
### One-time use connections
|
166
174
|
|
167
175
|
If you pass a block to RDO.connect, RDO yields the connection into the block,
|
168
|
-
returns the result of the block,
|
176
|
+
returns the result of the block, then closes the connection.
|
169
177
|
|
170
178
|
``` ruby
|
171
179
|
puts RDO.open("sqlite:some.db") do |c|
|
@@ -254,8 +262,8 @@ include any error messaage provided by the DBMS.
|
|
254
262
|
### Tread carefully, there be danger ahead
|
255
263
|
|
256
264
|
While driver developers are expected to provide a suitable implementation,
|
257
|
-
it is generally riskier to
|
258
|
-
|
265
|
+
it is generally riskier to escape and interpolate inputs directly into the
|
266
|
+
SQL than it is to use bind parameters. There are times where you might
|
259
267
|
need to escape some input yourself, however. For that, you can call #quote.
|
260
268
|
|
261
269
|
``` ruby
|
@@ -300,6 +308,10 @@ When sending pull requests, please use topic branches—don't send a pull
|
|
300
308
|
request from the master branch of your fork, as that may change
|
301
309
|
unintentionally.
|
302
310
|
|
311
|
+
I haven't looked at what I need to change to have the drivers compile on
|
312
|
+
Windows yet, but I will do. If anybody beats me to it, pull requests will
|
313
|
+
be gladly accepted! I'll probably add some thin JDBC wrappers for jRuby.
|
314
|
+
|
303
315
|
### Writing a driver for RDO
|
304
316
|
|
305
317
|
The more drivers that RDO has support for, the better. Writing drivers for
|
data/Rakefile
CHANGED
@@ -1,2 +1,14 @@
|
|
1
|
-
#!/usr/bin/env rake
|
2
1
|
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "rake/extensiontask"
|
4
|
+
|
5
|
+
Rake::ExtensionTask.new('rdo') do |ext|
|
6
|
+
ext.lib_dir = File.join('lib', 'rdo')
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Run the full RSpec suite"
|
10
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
11
|
+
t.pattern = 'spec/'
|
12
|
+
end
|
13
|
+
|
14
|
+
Rake::Task['spec'].prerequisites << :compile
|
data/ext/rdo/extconf.rb
ADDED
data/ext/rdo/rdo.c
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
/*
|
2
|
+
* RDO—Ruby Data Objects.
|
3
|
+
* Copyright © 2012 Chris Corbyn.
|
4
|
+
*
|
5
|
+
* See LICENSE file for details.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <ruby.h>
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <string.h>
|
11
|
+
|
12
|
+
/** Quote parameters in params array */
|
13
|
+
static char ** rdo_driver_quote_params(VALUE self, VALUE * args, int argc, long * len) {
|
14
|
+
char ** quoted = malloc(sizeof(char *) * argc);
|
15
|
+
int idx = 0;
|
16
|
+
VALUE tmp;
|
17
|
+
|
18
|
+
*len = 0;
|
19
|
+
|
20
|
+
for (; idx < argc; ++idx) {
|
21
|
+
switch (TYPE(args[idx])) {
|
22
|
+
case T_NIL:
|
23
|
+
quoted[idx] = strdup("NULL");
|
24
|
+
*len += 4;
|
25
|
+
break;
|
26
|
+
|
27
|
+
case T_FIXNUM:
|
28
|
+
case T_FLOAT:
|
29
|
+
tmp = rb_funcall(args[idx], rb_intern("to_s"), 0);
|
30
|
+
Check_Type(tmp, T_STRING);
|
31
|
+
|
32
|
+
quoted[idx] = strdup(RSTRING_PTR(tmp));
|
33
|
+
*len += RSTRING_LEN(tmp);
|
34
|
+
break;
|
35
|
+
|
36
|
+
default:
|
37
|
+
tmp = rb_funcall(self, rb_intern("quote"), 1, args[idx]);
|
38
|
+
Check_Type(tmp, T_STRING);
|
39
|
+
|
40
|
+
quoted[idx] = malloc(sizeof(char) * (RSTRING_LEN(tmp) + 3));
|
41
|
+
sprintf(quoted[idx], "'%s'", RSTRING_PTR(tmp));
|
42
|
+
*len += 2 + RSTRING_LEN(tmp);
|
43
|
+
break;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
return quoted;
|
48
|
+
}
|
49
|
+
|
50
|
+
/** Release heap memory allocated for quoted params */
|
51
|
+
static void rdo_driver_free_params(char ** quoted, int len) {
|
52
|
+
int i;
|
53
|
+
for (i = 0; i < len; ++i) free(quoted[i]);
|
54
|
+
free(quoted);
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Takes String stmt, which contains ? markers and interpolates the values in Array params.
|
59
|
+
*
|
60
|
+
* Each value in Array params that is not NilClass, Fixnum or Float is passed
|
61
|
+
* to #quote on the Driver.
|
62
|
+
*
|
63
|
+
* Non-numeric values are surrounded by String quote.
|
64
|
+
*
|
65
|
+
* @param VALUE (String) stmt
|
66
|
+
* SQL, possibly containining '?' markers.
|
67
|
+
*
|
68
|
+
* @param VALUE (Array) params
|
69
|
+
* arguments to interpolate in place of the ? markers
|
70
|
+
*
|
71
|
+
* @return VALUE (String)
|
72
|
+
* the same SQL with the parameters interpolated.
|
73
|
+
*/
|
74
|
+
static VALUE rdo_driver_interpolate(VALUE self, VALUE stmt, VALUE params) {
|
75
|
+
Check_Type(stmt, T_STRING);
|
76
|
+
Check_Type(params, T_ARRAY);
|
77
|
+
|
78
|
+
int argc = RARRAY_LEN(params);
|
79
|
+
long buflen = 0;
|
80
|
+
char ** quoted_params = rdo_driver_quote_params(
|
81
|
+
self,
|
82
|
+
RARRAY_PTR(params), argc,
|
83
|
+
&buflen);
|
84
|
+
char buffer[buflen + RSTRING_LEN(stmt) + 1];
|
85
|
+
|
86
|
+
char * b = buffer;
|
87
|
+
char * s = RSTRING_PTR(stmt);
|
88
|
+
int n = 0;
|
89
|
+
|
90
|
+
int insquote = 0;
|
91
|
+
int indquote = 0;
|
92
|
+
int inmlcmt = 0;
|
93
|
+
int inslcmt = 0;
|
94
|
+
|
95
|
+
// this loop is intentionally kept procedural (for performance)
|
96
|
+
for (; *s; ++s, ++b) {
|
97
|
+
switch (*s) {
|
98
|
+
case '?':
|
99
|
+
if (insquote || indquote || inmlcmt || inslcmt) {
|
100
|
+
*b = *s;
|
101
|
+
} else {
|
102
|
+
if (n < argc) {
|
103
|
+
strcpy(b, quoted_params[n]);
|
104
|
+
b += strlen(quoted_params[n]) - 1;
|
105
|
+
} else {
|
106
|
+
*b = *s;
|
107
|
+
}
|
108
|
+
++n;
|
109
|
+
}
|
110
|
+
break;
|
111
|
+
|
112
|
+
case '-':
|
113
|
+
if (!insquote && !indquote && !inmlcmt && *(s + 1) == '-') {
|
114
|
+
inslcmt = 1;
|
115
|
+
*(b++) = *(s++);
|
116
|
+
}
|
117
|
+
*b = *s;
|
118
|
+
break;
|
119
|
+
|
120
|
+
case '\r':
|
121
|
+
case '\n':
|
122
|
+
inslcmt = 0;
|
123
|
+
*b = *s;
|
124
|
+
break;
|
125
|
+
|
126
|
+
case '/':
|
127
|
+
if (!insquote && !indquote && !inslcmt && *(s + 1) == '*') {
|
128
|
+
++inmlcmt;
|
129
|
+
*(b++) = *(s++);
|
130
|
+
}
|
131
|
+
*b = *s;
|
132
|
+
break;
|
133
|
+
|
134
|
+
case '*':
|
135
|
+
if (inmlcmt && *(s + 1) == '/') {
|
136
|
+
--inmlcmt;
|
137
|
+
*(b++) = *(s++);
|
138
|
+
}
|
139
|
+
*b = *s;
|
140
|
+
break;
|
141
|
+
|
142
|
+
case '\'':
|
143
|
+
if (!indquote && !inmlcmt && !inslcmt) insquote = !insquote;
|
144
|
+
*b = *s;
|
145
|
+
break;
|
146
|
+
|
147
|
+
case '"':
|
148
|
+
if (!insquote && !inmlcmt && !inslcmt) indquote = !indquote;
|
149
|
+
*b = *s;
|
150
|
+
break;
|
151
|
+
|
152
|
+
default:
|
153
|
+
*b = *s;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
*b = '\0';
|
158
|
+
|
159
|
+
rdo_driver_free_params(quoted_params, argc);
|
160
|
+
|
161
|
+
if (n != argc) {
|
162
|
+
rb_raise(rb_eArgError,
|
163
|
+
"Bind parameter mismatch (%i for %i) in query %s",
|
164
|
+
argc, n, RSTRING_PTR(stmt));
|
165
|
+
}
|
166
|
+
|
167
|
+
return rb_str_new2(buffer);
|
168
|
+
}
|
169
|
+
|
170
|
+
/** Extension initializer */
|
171
|
+
void Init_rdo(void) {
|
172
|
+
rb_require("rdo/driver");
|
173
|
+
VALUE cDriver = rb_path2class("RDO::Driver");
|
174
|
+
rb_define_method(cDriver, "interpolate", rdo_driver_interpolate, 2);
|
175
|
+
}
|
data/lib/rdo.rb
CHANGED
data/lib/rdo/driver.rb
CHANGED
@@ -99,6 +99,9 @@ module RDO
|
|
99
99
|
|
100
100
|
# Escape a given value for safe interpolation into a statement.
|
101
101
|
#
|
102
|
+
# The value may be any type of Object and will be formatted to a String
|
103
|
+
# as needed.
|
104
|
+
#
|
102
105
|
# This should be avoided where the driver natively supports bind parameters.
|
103
106
|
#
|
104
107
|
# Drivers MUST override this with a RDBMS-specific solution.
|
@@ -111,6 +114,33 @@ module RDO
|
|
111
114
|
def quote(value)
|
112
115
|
end
|
113
116
|
|
117
|
+
protected
|
118
|
+
|
119
|
+
# Replace the values in params with the '?' markers in sql.
|
120
|
+
#
|
121
|
+
# This method exists for drivers that don't natively support bind
|
122
|
+
# parameters, or don't fully support them (e.g. MySQL). The
|
123
|
+
# implementation is done in C, since the scanning routine is
|
124
|
+
# considerably faster.
|
125
|
+
#
|
126
|
+
# Each value in params is processed according to its type:
|
127
|
+
#
|
128
|
+
# - NilClass, Fixnum, Float, inserted as literals (NULL or a number)
|
129
|
+
# - String passed through #quote, then wrapped in single quotes
|
130
|
+
# - All other objects converted to String then processed as a String
|
131
|
+
#
|
132
|
+
# @param [String] sql
|
133
|
+
# a String of SQL including '?' markers
|
134
|
+
#
|
135
|
+
# @param [Array] params
|
136
|
+
# an Array of objects to interpolate
|
137
|
+
#
|
138
|
+
# @return [String]
|
139
|
+
# the SQL to be executed
|
140
|
+
def interpolate(sql, params)
|
141
|
+
# implemented in ext/rdo/rdo.c
|
142
|
+
end
|
143
|
+
|
114
144
|
private
|
115
145
|
|
116
146
|
def emulated_statement_executor(stmt)
|
data/lib/rdo/version.rb
CHANGED
data/rdo.gemspec
CHANGED
@@ -21,7 +21,6 @@ Gem::Specification.new do |gem|
|
|
21
21
|
* Type casting to Ruby types
|
22
22
|
* Time zone handling (via the DBMS, not via some crazy time logic in Ruby)
|
23
23
|
* Native bind values parameterization of queries, where supported by the DBMS
|
24
|
-
* Buffered result sets (i.e. cursors, to avoid exhausting memory)
|
25
24
|
* Retrieve query info from executed commands (e.g. affected rows)
|
26
25
|
* Access RETURNING values just like any read query
|
27
26
|
* Native prepared statements where supported, emulated where not
|
@@ -48,6 +47,8 @@ Gem::Specification.new do |gem|
|
|
48
47
|
gem.name = "rdo"
|
49
48
|
gem.require_paths = ["lib"]
|
50
49
|
gem.version = RDO::VERSION
|
50
|
+
gem.extensions = ["ext/rdo/extconf.rb"]
|
51
51
|
|
52
52
|
gem.add_development_dependency "rspec"
|
53
|
+
gem.add_development_dependency "rake-compiler"
|
53
54
|
end
|
data/spec/rdo/driver_spec.rb
CHANGED
@@ -26,4 +26,100 @@ describe RDO::Driver do
|
|
26
26
|
stmt.execute(true).should be_a_kind_of(RDO::Result)
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
describe "#interpolate" do
|
31
|
+
let(:driver) { RDO::DriverWithBackwardsQuote.new }
|
32
|
+
|
33
|
+
it "interpolates nil as literal NULL" do
|
34
|
+
driver.send(:interpolate, "SELECT ?", [nil]).should == "SELECT NULL"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "interpolates a Fixnum as a literal integer" do
|
38
|
+
driver.send(:interpolate, "SELECT ? * 4", [123456789]).should == "SELECT 123456789 * 4"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "interpolates a Float as a literal float" do
|
42
|
+
driver.send(:interpolate, "SELECT ? * 4", [12.34]).should == "SELECT 12.34 * 4"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "interpolates a String as a quoted String" do
|
46
|
+
driver.send(:interpolate, "SELECT ?", ["string"]).should == "SELECT 'gnirts'"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "interpolates an Object as a quoted String" do
|
50
|
+
driver.send(:interpolate, "SELECT ?", [Date.new(2012, 9, 22)]).should == "SELECT '22-90-2102'"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "interpolates multiple params" do
|
54
|
+
driver.send(
|
55
|
+
:interpolate,
|
56
|
+
"SELECT ?, ?, ?",
|
57
|
+
["test", 42, nil]
|
58
|
+
).should == "SELECT 'tset', 42, NULL"
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with not enough params" do
|
62
|
+
it "raises an ArgumentError" do
|
63
|
+
expect {
|
64
|
+
driver.send(
|
65
|
+
:interpolate,
|
66
|
+
"SELECT ?, ?, ?",
|
67
|
+
["test", 42]
|
68
|
+
)
|
69
|
+
}.to raise_error(ArgumentError)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with too many params" do
|
74
|
+
it "raises an ArgumentError" do
|
75
|
+
expect {
|
76
|
+
driver.send(
|
77
|
+
:interpolate,
|
78
|
+
"SELECT ?, ?",
|
79
|
+
["test", 42, nil]
|
80
|
+
)
|
81
|
+
}.to raise_error(ArgumentError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "with marks placed inside single quotes" do
|
86
|
+
it "ignores the quoted marks" do
|
87
|
+
driver.send(
|
88
|
+
:interpolate,
|
89
|
+
"SELECT 'quoted?', ?, ?",
|
90
|
+
["test", 42]
|
91
|
+
).should == "SELECT 'quoted?', 'tset', 42"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "with marks placed inside double quotes" do
|
96
|
+
it "ignores the quoted marks" do
|
97
|
+
driver.send(
|
98
|
+
:interpolate,
|
99
|
+
"SELECT \"quoted?\", ?, ?",
|
100
|
+
["test", 42]
|
101
|
+
).should == "SELECT \"quoted?\", 'tset', 42"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "with marks placed inside multiline comments" do
|
106
|
+
it "ignores the comments marks" do
|
107
|
+
driver.send(
|
108
|
+
:interpolate,
|
109
|
+
"SELECT /* commented? */ ?, ?",
|
110
|
+
["test", 42]
|
111
|
+
).should == "SELECT /* commented? */ 'tset', 42"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "with marks placed inside line comments" do
|
116
|
+
it "ignores the comments marks" do
|
117
|
+
driver.send(
|
118
|
+
:interpolate,
|
119
|
+
"SELECT\n -- commented?\n ?, ?",
|
120
|
+
["test", 42]
|
121
|
+
).should == "SELECT\n -- commented?\n 'tset', 42"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
29
125
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rdo"
|
2
|
+
|
3
|
+
module RDO
|
4
|
+
class DriverWithBackwardsQuote < Driver
|
5
|
+
def open
|
6
|
+
@open = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def open?
|
10
|
+
!!@open
|
11
|
+
end
|
12
|
+
|
13
|
+
def close
|
14
|
+
@open = false
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(stmt, *args)
|
19
|
+
Result.new([])
|
20
|
+
end
|
21
|
+
|
22
|
+
def quote(obj)
|
23
|
+
obj.to_s.reverse
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
Connection.register_driver(:rdo_with_backwards_quote, DriverWithBackwardsQuote)
|
28
|
+
end
|
29
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake-compiler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
description: ! "== Ruby Data Objects\n\nIf you're building something in Ruby that
|
31
47
|
needs access to a database, you may\nopt to use an ORM like ActiveRecord, DataMapper
|
32
48
|
or Sequel. But if your needs\ndon't fit well with an ORM—maybe you're even writing
|
@@ -36,27 +52,30 @@ description: ! "== Ruby Data Objects\n\nIf you're building something in Ruby tha
|
|
36
52
|
library:\n\n * Consistent API to connect to various DBMS's\n * Type casting to
|
37
53
|
Ruby types\n * Time zone handling (via the DBMS, not via some crazy time logic
|
38
54
|
in Ruby)\n * Native bind values parameterization of queries, where supported by
|
39
|
-
the DBMS\n *
|
40
|
-
\ *
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
C.\n\nSee the official README for full details."
|
55
|
+
the DBMS\n * Retrieve query info from executed commands (e.g. affected rows)\n
|
56
|
+
\ * Access RETURNING values just like any read query\n * Native prepared statements
|
57
|
+
where supported, emulated where not\n * Results given using simple core Ruby data
|
58
|
+
types\n\n== RDBMS Support\n\nSupport for each RDBMS is provided in separate gems,
|
59
|
+
so as to minimize the\ninstallation requirements and to facilitate the maintenace
|
60
|
+
of each driver. Many\ngems are maintained by separate users who work more closely
|
61
|
+
with those RDBMS's.\n\nDue to the nature of this gem, most of the nitty-gritty code
|
62
|
+
is actually\nwritten in C.\n\nSee the official README for full details."
|
48
63
|
email:
|
49
64
|
- chris@w3style.co.uk
|
50
65
|
executables: []
|
51
|
-
extensions:
|
66
|
+
extensions:
|
67
|
+
- ext/rdo/extconf.rb
|
52
68
|
extra_rdoc_files: []
|
53
69
|
files:
|
54
70
|
- .gitignore
|
55
71
|
- .rspec
|
72
|
+
- .travis.yml
|
56
73
|
- Gemfile
|
57
74
|
- LICENSE
|
58
75
|
- README.md
|
59
76
|
- Rakefile
|
77
|
+
- ext/rdo/extconf.rb
|
78
|
+
- ext/rdo/rdo.c
|
60
79
|
- lib/rdo.rb
|
61
80
|
- lib/rdo/connection.rb
|
62
81
|
- lib/rdo/driver.rb
|
@@ -75,6 +94,7 @@ files:
|
|
75
94
|
- spec/rdo/statement_spec.rb
|
76
95
|
- spec/rdo/util_spec.rb
|
77
96
|
- spec/spec_helper.rb
|
97
|
+
- spec/support/driver_with_backwards_quote.rb
|
78
98
|
- spec/support/driver_with_everything.rb
|
79
99
|
- spec/support/driver_without_statements.rb
|
80
100
|
- util/macros.h
|
@@ -111,5 +131,6 @@ test_files:
|
|
111
131
|
- spec/rdo/statement_spec.rb
|
112
132
|
- spec/rdo/util_spec.rb
|
113
133
|
- spec/spec_helper.rb
|
134
|
+
- spec/support/driver_with_backwards_quote.rb
|
114
135
|
- spec/support/driver_with_everything.rb
|
115
136
|
- spec/support/driver_without_statements.rb
|