nuodb 1.0.2 → 1.1
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 +1 -0
- data/.travis.yml +11 -6
- data/{CONTRIBUTION.rdoc → CONTRIBUTION.md} +20 -19
- data/Gemfile +1 -1
- data/Gemfile.lock +56 -0
- data/History.txt +3 -0
- data/README.md +43 -0
- data/Rakefile +1 -1
- data/ext/nuodb/nuodb.cpp +440 -790
- data/lib/nuodb/version.rb +1 -1
- data/nuodb.gemspec +1 -1
- data/spec/functional/datatypes_spec.rb +1 -1
- data/spec/functional/generated_keys_spec.rb +7 -4
- data/spec/functional/statement_spec.rb +7 -6
- metadata +57 -28
- checksums.yaml +0 -7
- data/README.rdoc +0 -36
- data/install-nuodb.sh +0 -5
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
3
|
rvm:
|
4
|
+
- 2.0.0
|
4
5
|
- 1.9.3
|
5
6
|
|
6
7
|
env:
|
7
|
-
- NUODB_ROOT=/opt/nuodb
|
8
|
+
- NUODB_ROOT=/opt/nuodb NUODB_VERSION=1.2
|
9
|
+
- NUODB_ROOT=/opt/nuodb NUODB_VERSION=1.1.1
|
10
|
+
- NUODB_ROOT=/opt/nuodb NUODB_VERSION=1.1
|
11
|
+
- NUODB_ROOT=/opt/nuodb NUODB_VERSION=1.0.2
|
12
|
+
- NUODB_ROOT=/opt/nuodb NUODB_VERSION=1.0.1
|
8
13
|
|
9
14
|
notifications:
|
10
15
|
recipients:
|
@@ -13,19 +18,19 @@ notifications:
|
|
13
18
|
- lbayas@nuodb.com
|
14
19
|
|
15
20
|
before_install:
|
16
|
-
- wget http://www.nuodb.com/latest/nuodb
|
21
|
+
- wget http://www.nuodb.com/latest/releases/nuodb-${NUODB_VERSION}.linux.x64.deb --output-document=/var/tmp/nuodb.deb
|
17
22
|
- sudo dpkg -i /var/tmp/nuodb.deb
|
18
23
|
- sleep 2
|
19
24
|
|
20
25
|
before_script:
|
21
26
|
- ${NUODB_ROOT}/bin/nuodb --chorus test --password bar --dba-user dba --dba-password baz --verbose debug --archive /var/tmp/nuodb --initialize --force &
|
22
|
-
- sleep
|
27
|
+
- sleep 4
|
23
28
|
- ${NUODB_ROOT}/bin/nuodb --chorus test --password bar --dba-user dba --dba-password baz &
|
24
|
-
- sleep
|
29
|
+
- sleep 4
|
25
30
|
- echo "create user cloud password 'user';" | ${NUODB_ROOT}/bin/nuosql test@localhost --user dba --password baz
|
26
31
|
|
27
32
|
script:
|
28
|
-
- NUODB_ROOT=/opt/nuodb bundle exec rake spec
|
33
|
+
- NUODB_ROOT=/opt/nuodb bundle exec rake spec
|
29
34
|
|
30
35
|
after_script:
|
31
|
-
- sudo dpkg -r nuodb
|
36
|
+
- sudo dpkg -r nuodb
|
@@ -1,20 +1,20 @@
|
|
1
|
-
|
1
|
+
# Contributing to the Ruby NuoDB Driver
|
2
2
|
|
3
|
-
|
3
|
+
## BUILDING THE GEM
|
4
4
|
|
5
5
|
To compile and test run this command:
|
6
6
|
|
7
7
|
rake clean build rdoc spec
|
8
8
|
|
9
|
-
|
9
|
+
## INSTALLING THE GEM
|
10
10
|
|
11
|
-
NUODB_ROOT=/Users/rbuck/tmp/nuodb gem install nuodb-1.
|
11
|
+
NUODB_ROOT=/Users/rbuck/tmp/nuodb gem install nuodb-1.1.gem
|
12
12
|
|
13
13
|
Or from the source tree:
|
14
14
|
|
15
|
-
NUODB_ROOT=/Users/rbuck/tmp/nuodb gem install pkg/nuodb-1.
|
15
|
+
NUODB_ROOT=/Users/rbuck/tmp/nuodb gem install pkg/nuodb-1.1.gem
|
16
16
|
|
17
|
-
|
17
|
+
## TESTING THE GEM
|
18
18
|
|
19
19
|
Start up a minimal chorus as follows:
|
20
20
|
|
@@ -32,33 +32,34 @@ Run the tests:
|
|
32
32
|
|
33
33
|
rake spec
|
34
34
|
|
35
|
-
|
35
|
+
## PUBLISHING THE GEM
|
36
36
|
|
37
|
-
|
37
|
+
### TAGGING
|
38
38
|
|
39
|
-
Tag the product using tags per the SemVer specification; our tags have a
|
39
|
+
Tag the product using tags per the SemVer specification; our tags have a
|
40
|
+
v-prefix:
|
40
41
|
|
41
|
-
git tag -a v1.
|
42
|
+
git tag -a v1.1 -m "SemVer Version: v1.1"
|
42
43
|
|
43
44
|
If you make a mistake, take it back quickly:
|
44
45
|
|
45
|
-
git tag -d v1.
|
46
|
-
git push origin :refs/tags/v1.
|
46
|
+
git tag -d v1.1
|
47
|
+
git push origin :refs/tags/v1.1
|
47
48
|
|
48
|
-
|
49
|
+
### PUBLISHING
|
49
50
|
|
50
51
|
Here are the commands used to publish:
|
51
52
|
|
52
|
-
gem push pkg/nuodb-1.
|
53
|
+
gem push pkg/nuodb-1.1.gem
|
53
54
|
|
54
|
-
|
55
|
+
## INSPECTING THE GEM
|
55
56
|
|
56
|
-
It is often useful to inspect the contents of a Gem before distribution.
|
57
|
-
|
57
|
+
It is often useful to inspect the contents of a Gem before distribution. To do
|
58
|
+
this you dump the contents of a gem thus:
|
58
59
|
|
59
|
-
gem unpack pkg/nuodb-1.
|
60
|
+
gem unpack pkg/nuodb-1.1.gem
|
60
61
|
|
61
|
-
|
62
|
+
## INSPECTING THE EXPORTED SYMBOLS
|
62
63
|
|
63
64
|
To inspec the symbols on Linux:
|
64
65
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nuodb (1.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
erubis (2.7.0)
|
11
|
+
haml (3.0.25)
|
12
|
+
hanna-nouveau (0.2.7)
|
13
|
+
haml (= 3.0.25)
|
14
|
+
rdoc (~> 3.1)
|
15
|
+
json (1.8.0)
|
16
|
+
multi_json (1.7.9)
|
17
|
+
optiflag (0.7)
|
18
|
+
rake (10.1.0)
|
19
|
+
rdoc (3.12.2)
|
20
|
+
json (~> 1.4)
|
21
|
+
rspec (2.11.0)
|
22
|
+
rspec-core (~> 2.11.0)
|
23
|
+
rspec-expectations (~> 2.11.0)
|
24
|
+
rspec-mocks (~> 2.11.0)
|
25
|
+
rspec-core (2.11.1)
|
26
|
+
rspec-expectations (2.11.3)
|
27
|
+
diff-lcs (~> 1.1.3)
|
28
|
+
rspec-mocks (2.11.3)
|
29
|
+
ruby-prof (0.13.0)
|
30
|
+
rubydoc (0.0.1)
|
31
|
+
optiflag (~> 0.7)
|
32
|
+
sdoc (0.3.20)
|
33
|
+
json (>= 1.1.3)
|
34
|
+
rdoc (~> 3.10)
|
35
|
+
simplecov (0.7.1)
|
36
|
+
multi_json (~> 1.0)
|
37
|
+
simplecov-html (~> 0.7.1)
|
38
|
+
simplecov-html (0.7.1)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
erubis (~> 2.7.0)
|
45
|
+
hanna-nouveau
|
46
|
+
nuodb!
|
47
|
+
rake (~> 10.1.0)
|
48
|
+
rdoc
|
49
|
+
rspec (~> 2.11.0)
|
50
|
+
rspec-core (~> 2.11.0)
|
51
|
+
rspec-expectations (~> 2.11.0)
|
52
|
+
rspec-mocks (~> 2.11.0)
|
53
|
+
ruby-prof
|
54
|
+
rubydoc
|
55
|
+
sdoc
|
56
|
+
simplecov
|
data/History.txt
CHANGED
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Ruby/NuoDB Interface [<img src="https://api.travis-ci.org/nuodb/ruby-nuodb.png?branch=master" alt="Build Status" />](http://travis-ci.org/nuodb/ruby-nuodb) [<img src="https://gemnasium.com/nuodb/ruby-nuodb.png?travis" alt="Dependency Status" />](https://gemnasium.com/nuodb/ruby-nuodb) [<img src="https://codeclimate.com/github/nuodb/ruby-nuodb.png" />](https://codeclimate.com/github/nuodb/ruby-nuodb)
|
2
|
+
|
3
|
+
This is the official Ruby Gem for [NuoDB](http://www.nuodb.com/). It wraps the
|
4
|
+
NuoDB C++ API, providing a natural API for Ruby.
|
5
|
+
|
6
|
+
To use NuoDB with Rails you will also want the [ActiveRecord NuoDB
|
7
|
+
Adapter](https://github.com/nuodb/ruby-activerecord-nuodb-adapter)
|
8
|
+
|
9
|
+
Note: At this time the Ruby/NuoDB Interface does not support Windows.
|
10
|
+
|
11
|
+
## Getting Started
|
12
|
+
|
13
|
+
1. If you haven't already, [Download and Install NuoDB](http://nuodb.com/download-nuodb/)
|
14
|
+
|
15
|
+
2. Install the gem
|
16
|
+
|
17
|
+
gem install nuodb
|
18
|
+
|
19
|
+
3. Use NuoDB in Ruby
|
20
|
+
|
21
|
+
require "nuodb"
|
22
|
+
|
23
|
+
conn = NuoDB::Connection.new(:database => 'test@localhost', :username => 'dba', :password => 'goalie', :schema => 'hockey')
|
24
|
+
stmt = conn.statement
|
25
|
+
stmt.execute("SELECT * FROM hockey")
|
26
|
+
stmt.results.each do |res|
|
27
|
+
puts res.inspect
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
## More Information
|
32
|
+
|
33
|
+
* [Ruby/NuoDB Interface Rdoc](http://nuodb.github.io/ruby-nuodb/rdoc/)
|
34
|
+
* [NuoDB Community Forum](http://www.nuodb.com/community/forum.php)
|
35
|
+
* [NuoDB Online Documentation](http://www.nuodb.com/community/documentation.php)
|
36
|
+
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
See [Contribution](CONTRIBUTION.md) for information about contributing to
|
41
|
+
the Ruby ActiveRecord NuoDB Adapter.
|
42
|
+
|
43
|
+
[](http://githalytics.com/nuodb/ruby-nuodb)
|
data/Rakefile
CHANGED
@@ -129,7 +129,7 @@ namespace :nuodb do
|
|
129
129
|
case RUBY_PLATFORM
|
130
130
|
when /linux/i
|
131
131
|
unless File.exists? '/etc/redhat-release'
|
132
|
-
puts %x(wget http://www.nuodb.com/latest/nuodb-1.
|
132
|
+
puts %x(wget http://www.nuodb.com/latest/releases/nuodb-1.1.linux.x64.deb --output-document=/var/tmp/nuodb.deb)
|
133
133
|
puts %x(sudo dpkg -i /var/tmp/nuodb.deb)
|
134
134
|
end
|
135
135
|
else
|
data/ext/nuodb/nuodb.cpp
CHANGED
@@ -36,17 +36,21 @@
|
|
36
36
|
#include <time.h>
|
37
37
|
#include <stdio.h>
|
38
38
|
#include <typeinfo>
|
39
|
+
#include <stdarg.h>
|
40
|
+
|
41
|
+
#define NANOS_PER_SECOND 1000000000
|
42
|
+
#define NANOS_PER_MICRO 1000
|
39
43
|
|
40
44
|
#define HAVE_CXA_DEMANGLE
|
41
45
|
|
42
46
|
#ifdef HAVE_CXA_DEMANGLE
|
43
47
|
#include <cxxabi.h>
|
44
|
-
const char
|
48
|
+
const char* demangle(const char* name)
|
45
49
|
{
|
46
50
|
char buf[1024];
|
47
51
|
size_t size = 1024;
|
48
52
|
int status;
|
49
|
-
char
|
53
|
+
char* res = abi::__cxa_demangle (name,
|
50
54
|
buf, &size, &status);
|
51
55
|
return res;
|
52
56
|
}
|
@@ -121,19 +125,19 @@ static const bool ENABLE_CLOSE_HOOK = true;
|
|
121
125
|
|
122
126
|
enum LogLevel
|
123
127
|
{
|
124
|
-
ERROR,
|
125
|
-
WARN,
|
126
|
-
INFO,
|
127
128
|
TRACE,
|
128
129
|
DEBUG,
|
130
|
+
INFO,
|
131
|
+
WARN,
|
132
|
+
ERROR,
|
129
133
|
NONE
|
130
134
|
};
|
131
135
|
|
132
|
-
static LogLevel logLevel =
|
136
|
+
static LogLevel logLevel = ERROR;
|
133
137
|
|
134
|
-
static char const
|
138
|
+
static char const* log_level_name(LogLevel level)
|
135
139
|
{
|
136
|
-
char const
|
140
|
+
char const* level_name = NULL;
|
137
141
|
switch(level)
|
138
142
|
{
|
139
143
|
case NONE:
|
@@ -158,7 +162,7 @@ static char const * log_level_name(LogLevel level)
|
|
158
162
|
return level_name;
|
159
163
|
}
|
160
164
|
|
161
|
-
static void log(LogLevel level, char const
|
165
|
+
static void log(LogLevel level, char const* message)
|
162
166
|
{
|
163
167
|
if (level >= logLevel)
|
164
168
|
{
|
@@ -166,17 +170,17 @@ static void log(LogLevel level, char const * message)
|
|
166
170
|
}
|
167
171
|
}
|
168
172
|
|
169
|
-
static void trace(char const
|
173
|
+
static void trace(char const* message)
|
170
174
|
{
|
171
175
|
log(TRACE, message);
|
172
176
|
}
|
173
177
|
|
174
|
-
static void print_address(char const
|
178
|
+
static void print_address(char const* context, void* address)
|
175
179
|
{
|
176
180
|
if (DEBUG >= logLevel)
|
177
181
|
{
|
178
182
|
unsigned char *p = (unsigned char *)&address;
|
179
|
-
int i;
|
183
|
+
unsigned int i;
|
180
184
|
printf("%s: ", context);
|
181
185
|
for (i = 0; i < sizeof address; i++)
|
182
186
|
{
|
@@ -187,137 +191,35 @@ static void print_address(char const * context, void * address)
|
|
187
191
|
}
|
188
192
|
|
189
193
|
// ----------------------------------------------------------------------------
|
190
|
-
//
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
/*
|
195
|
-
* GC Notes:
|
196
|
-
*
|
197
|
-
* 1. gc_entities are placed in the Ruby object table and are freed via mark
|
198
|
-
* and sweep.
|
199
|
-
* 2. gc_entities may be freed in any order.
|
200
|
-
* 3. gc_entities may be freed either before shutdown or during shutdown.
|
201
|
-
* 4. gc_entities may no longer be accessed once freed by the garbage
|
202
|
-
* collector; once gc_entities are freed they no longer appear in the
|
203
|
-
* object table. As such, calls to Data_Get_Struct on previously garbage
|
204
|
-
* collected entities will cause the Ruby VM to crash; viz. SIGABRT via
|
205
|
-
* EXC_BAD_ACCESS.
|
206
|
-
*
|
207
|
-
* a. So a general observation of this is thusly: if e.g. with graphs of
|
208
|
-
* child to parent relationships an orderly de-allocation is required,
|
209
|
-
* as parents (gc_entities) may be freed prior to childrens (gc_entities)
|
210
|
-
* it becomes imperative that the logic between freeing gc_entity objects
|
211
|
-
* be kept completely and distinctly apart from the logic of the managed
|
212
|
-
* entities themselves.
|
213
|
-
*/
|
214
|
-
|
215
|
-
typedef void (*callback)(void *);
|
216
|
-
|
217
|
-
/*
|
218
|
-
* Application Rules:
|
219
|
-
*
|
220
|
-
* 1. Assign a callback for the increment and decrement refers counter so that
|
221
|
-
* context specific logging and tracking may be implemented.
|
222
|
-
* 2. Direct access to refers should never occur.
|
223
|
-
* 3. The freed bit indicates that the resources associated to the data_handle
|
224
|
-
* has been freed, and NOT that the os_entity struct has been freed.
|
225
|
-
*
|
226
|
-
* Logic:
|
227
|
-
*
|
228
|
-
* 1. The incr_func is called on a child when it is first created.
|
229
|
-
* 2. The incr_func is called on a parent when its child is first created.
|
230
|
-
* 3. When incr_func is called, ATOMIC_INC increments the refers field.
|
231
|
-
* 4. When decr_func is called, ATOMIC_DEC decrements the refers field.
|
232
|
-
* 5. When the refers field reaches zero (inside decr_func):
|
233
|
-
* 5.1. ATOMIC-CAS the freed bit, if the prior freed bit is not set:
|
234
|
-
* 5.1.1. ATOMIC-OR all parents freed bits and if the result does not have
|
235
|
-
* the freed bit set:
|
236
|
-
* 5.1.1.1. Call the free function, passing the os_entity itself as a parameter.
|
237
|
-
* The free function releases any resources related to the data
|
238
|
-
* handle itself and sets the handle to null.
|
239
|
-
* 5.2. Call the decr_func on its parent (this may act recursively).
|
240
|
-
* 5.3. Call xfree on the os_entity structure itself.
|
241
|
-
* 6. When a user calls finish on an object:
|
242
|
-
* 6.1. ATOMIC-CAS the freed bit, if the prior freed bit is not set
|
243
|
-
* perform operations 5.1.1 through 5.1.1.1.
|
244
|
-
*
|
245
|
-
* Details:
|
246
|
-
*
|
247
|
-
* 1. Regarding 5a, above, we neither want to doubly release an object, nor
|
248
|
-
* call free_function when a parent has already released all the resources.
|
249
|
-
* This optionally is configurable, for cases when parents forcibly close
|
250
|
-
* child resources, or for cases where they don't. This is a behavioral
|
251
|
-
* configuration parameter to the resource manager. But the above documentation
|
252
|
-
* is tailored for cases where parents automatically release child resources
|
253
|
-
* when they themselves are closed.
|
254
|
-
* 2. A race condition may occur between 5.1 and 5.2, above, where a parent
|
255
|
-
* resource is released just after 5.1.1.1 and before 5.2; the result will
|
256
|
-
* be a SEGV. This may prompt the use of a global lock for the reference
|
257
|
-
* manager.
|
258
|
-
*
|
259
|
-
* Interface:
|
260
|
-
*
|
261
|
-
* 1. Structures as defined below.
|
262
|
-
* 2. Function to release a reference:
|
263
|
-
* void rc_decr_refs (void * handle, int * err_code)
|
264
|
-
* 3. Function to acquire a reference:
|
265
|
-
* void rc_incr_refs (void * handle, int * err_code)
|
266
|
-
* 4. Function to wrap an entity:
|
267
|
-
* void * rc_add_object (void * object, int * err_code)
|
268
|
-
* 5. Function to get wrapped pointer:
|
269
|
-
* void * rc_get_object (void * handle, int * err_code)
|
270
|
-
*
|
271
|
-
* Questions:
|
272
|
-
*
|
273
|
-
* 1. Do we go opaque so that the data type definition is malleable? We don't
|
274
|
-
* want this any more type specific than it is.
|
275
|
-
*/
|
276
|
-
struct os_entity
|
277
|
-
{
|
278
|
-
void * data_handle;
|
279
|
-
unsigned int flags;
|
280
|
-
rb_atomic_t refers;
|
281
|
-
|
282
|
-
callback incr_func;
|
283
|
-
callback decr_func;
|
284
|
-
callback free_func;
|
285
|
-
|
286
|
-
os_entity * parent;
|
287
|
-
};
|
194
|
+
// H A N D L E S
|
195
|
+
//
|
196
|
+
//
|
288
197
|
|
289
198
|
/*
|
290
|
-
*
|
199
|
+
* Each nuodb client datatype that we need to expose to ruby will be done via a handle object. The handle contains
|
200
|
+
* two kinds of things, a pointer to a client instance and GC handling information. The GC information is there to
|
201
|
+
* deal with the fact that the nuodb client API requires that things be closed before they are deallocated and that
|
202
|
+
* the closures happen in a very specific order. Namely, that all result sets are closed before their creating
|
203
|
+
* statement can be closed. And that all statements are closed before their creating connection may be closed.
|
204
|
+
* Ruby's GC hooks allow us to hook into the MARK phase so that all objects may mark their parents to prevent that
|
205
|
+
* out-of-order condition. However, ruby guarantees no particular order when freeing objects determined to be
|
206
|
+
* garbage. Therefore the GC thread may invoke free on a statement before it's result set even though both are
|
207
|
+
* garbage and will eventually be freed in the same sweep. Therefore, each handle also has a numUsed reference
|
208
|
+
* count. On creation, a handle increments its parent's numUsed. On free, a handle decrements its parent's numUsed.
|
209
|
+
* A handle cannot be freed if its numUsed is greater than 0. Therefore, it is the responsibility of every child to
|
210
|
+
* check if it needs to clean up its parent.
|
291
211
|
*
|
292
|
-
*
|
293
|
-
*
|
294
|
-
* 2. When the garbage collector frees an object, the decr_function is called
|
295
|
-
* on the entity passing the entity as its parameter.
|
212
|
+
* When a handle has finally been deemed to be free-able, the cleanupFunc needs to be called to actually close out
|
213
|
+
* the handle's client instances.
|
296
214
|
*/
|
297
|
-
struct gc_entity
|
298
|
-
{
|
299
|
-
os_entity * entity;
|
300
|
-
VALUE ** mark_refs;
|
301
|
-
};
|
302
|
-
|
303
|
-
/*
|
304
|
-
* A strict release strategy only permits free calls after the reference count
|
305
|
-
* drops to zero. A lenient release strategy permits free calls at any time,
|
306
|
-
* yet the entity itself is not freed until its reference count drops to zero.
|
307
|
-
*/
|
308
|
-
typedef enum {strict, lenient} free_strategy;
|
309
|
-
|
310
|
-
#endif /* ENABLE_NEXTGEN_GC_INTEGRATION */
|
311
|
-
|
312
|
-
// ----------------------------------------------------------------------------
|
313
|
-
// H A N D L E S
|
314
215
|
|
315
216
|
struct nuodb_handle
|
316
217
|
{
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
218
|
+
bool freePending; //GC wants to free us, but we still have some children outstanding
|
219
|
+
void (*cleanupFunc)(nuodb_handle*); //cleanup function
|
220
|
+
|
221
|
+
int numUsed; //number of surviving children to prevent premature free
|
222
|
+
nuodb_handle* parent;
|
321
223
|
};
|
322
224
|
|
323
225
|
struct nuodb_connection_handle : nuodb_handle
|
@@ -328,128 +230,59 @@ struct nuodb_connection_handle : nuodb_handle
|
|
328
230
|
VALUE schema;
|
329
231
|
VALUE timezone;
|
330
232
|
|
331
|
-
NuoDB::Connection
|
233
|
+
NuoDB::Connection* pointer;
|
332
234
|
};
|
333
235
|
|
334
236
|
struct nuodb_prepared_statement_handle : nuodb_handle
|
335
237
|
{
|
336
|
-
NuoDB::PreparedStatement
|
238
|
+
NuoDB::PreparedStatement* pointer;
|
239
|
+
|
240
|
+
VALUE connection;
|
241
|
+
nuodb_connection_handle* connection_handle;
|
337
242
|
};
|
338
243
|
|
339
244
|
struct nuodb_statement_handle : nuodb_handle
|
340
245
|
{
|
341
|
-
NuoDB::Statement
|
246
|
+
NuoDB::Statement* pointer;
|
247
|
+
|
248
|
+
VALUE connection;
|
249
|
+
nuodb_connection_handle* connection_handle;
|
342
250
|
};
|
343
251
|
|
344
252
|
struct nuodb_result_handle : nuodb_handle
|
345
253
|
{
|
346
|
-
NuoDB::ResultSet
|
347
|
-
NuoDB::Connection
|
254
|
+
NuoDB::ResultSet* pointer;
|
255
|
+
NuoDB::Connection* connection;
|
256
|
+
|
257
|
+
VALUE statement;
|
258
|
+
int columnCount;
|
259
|
+
NuoDB::SqlType* types;
|
260
|
+
NuoDB::ResultSetMetaData* resultMetaData;
|
261
|
+
|
262
|
+
nuodb_prepared_statement_handle* prepStmt;
|
263
|
+
nuodb_statement_handle* stmt;
|
348
264
|
};
|
349
265
|
|
350
266
|
template<typename handle_type>
|
351
|
-
handle_type
|
267
|
+
handle_type* cast_handle(VALUE value)
|
352
268
|
{
|
353
269
|
Check_Type(value, T_DATA);
|
354
270
|
return static_cast<handle_type*>(DATA_PTR(value));
|
355
271
|
}
|
356
272
|
|
357
273
|
template<typename handle_type, typename return_type>
|
358
|
-
return_type
|
274
|
+
return_type* cast_pointer_member(VALUE value)
|
359
275
|
{
|
360
276
|
Check_Type(value, T_DATA);
|
361
277
|
return cast_handle<handle_type>(value)->pointer;
|
362
278
|
}
|
363
279
|
|
364
|
-
static void track_ref_count(char const * context, nuodb_handle * handle)
|
365
|
-
{
|
366
|
-
trace("track_ref_count");
|
367
|
-
|
368
|
-
if (handle != 0)
|
369
|
-
{
|
370
|
-
int parent_count = -10;
|
371
|
-
if (handle->parent_handle != 0)
|
372
|
-
{
|
373
|
-
parent_count = handle->parent_handle->atomic;
|
374
|
-
}
|
375
|
-
if (logLevel <= DEBUG)
|
376
|
-
{
|
377
|
-
nuodb_handle * parent = handle->parent_handle;
|
378
|
-
unsigned char *p = (unsigned char *)&handle;
|
379
|
-
unsigned char *q = (unsigned char *)&parent;
|
380
|
-
int i;
|
381
|
-
printf("[REFERENCE COUNT][%s] (%s @ ", context, demangle(typeid(*handle).name()));
|
382
|
-
for (i = 0; i < sizeof handle; i++)
|
383
|
-
{
|
384
|
-
printf("%02x ", p[i]);
|
385
|
-
}
|
386
|
-
printf("): %d (%s @ ", handle->atomic, demangle(typeid(*parent).name()));
|
387
|
-
for (i = 0; i < sizeof parent; i++)
|
388
|
-
{
|
389
|
-
printf("%02x ", q[i]);
|
390
|
-
}
|
391
|
-
printf("): %d", parent_count);
|
392
|
-
putchar('\n');
|
393
|
-
}
|
394
|
-
}
|
395
|
-
}
|
396
|
-
|
397
|
-
void incr_reference_count(nuodb_handle * handle)
|
398
|
-
{
|
399
|
-
trace("incr_reference_count");
|
400
|
-
|
401
|
-
track_ref_count("I INCR", handle);
|
402
|
-
|
403
|
-
ATOMIC_INC(handle->atomic);
|
404
|
-
if (handle->parent_handle != 0)
|
405
|
-
{
|
406
|
-
log(DEBUG, "incrementing parent");
|
407
|
-
ATOMIC_INC(handle->parent_handle->atomic);
|
408
|
-
}
|
409
|
-
|
410
|
-
track_ref_count("O INCR", handle);
|
411
|
-
}
|
412
|
-
|
413
|
-
void decr_reference_count(nuodb_handle * handle)
|
414
|
-
{
|
415
|
-
trace("decr_reference_count");
|
416
|
-
|
417
|
-
track_ref_count("I DECR", handle);
|
418
|
-
|
419
|
-
if (handle->atomic == 0)
|
420
|
-
{
|
421
|
-
return;
|
422
|
-
}
|
423
|
-
|
424
|
-
if (ATOMIC_DEC(handle->atomic) == 0)
|
425
|
-
{
|
426
|
-
(*(handle->free_func))(handle);
|
427
|
-
if (handle->parent_handle != 0)
|
428
|
-
{
|
429
|
-
log(DEBUG, "decrementing parent");
|
430
|
-
decr_reference_count(handle->parent_handle);
|
431
|
-
handle->parent = Qnil;
|
432
|
-
handle->parent_handle = 0;
|
433
|
-
assert(NIL_P(handle->parent));
|
434
|
-
}
|
435
|
-
track_ref_count("O DECR", handle);
|
436
|
-
|
437
|
-
print_address("[DELETING HANDLE]", handle);
|
438
|
-
xfree(handle);
|
439
|
-
handle = NULL;
|
440
|
-
}
|
441
|
-
else
|
442
|
-
{
|
443
|
-
track_ref_count("O DECR", handle);
|
444
|
-
}
|
445
|
-
}
|
446
|
-
|
447
280
|
//------------------------------------------------------------------------------
|
448
281
|
// exception mapper
|
449
282
|
|
450
283
|
static ID c_error_code_assignment;
|
451
284
|
|
452
|
-
static void rb_raise_nuodb_error(int code, const char
|
285
|
+
static void rb_raise_nuodb_error(int code, const char* fmt, ...)
|
453
286
|
{
|
454
287
|
va_list args;
|
455
288
|
char text[BUFSIZ];
|
@@ -468,60 +301,124 @@ static void rb_raise_nuodb_error(int code, const char * fmt, ...)
|
|
468
301
|
using namespace NuoDB;
|
469
302
|
|
470
303
|
//------------------------------------------------------------------------------
|
304
|
+
//
|
305
|
+
//
|
306
|
+
static
|
307
|
+
void handle_init(nuodb_handle* self, nuodb_handle* parent, int initialChildren, void (*cleaner)(nuodb_handle*))
|
308
|
+
{
|
309
|
+
self->numUsed = 0;
|
310
|
+
self->freePending = false;
|
311
|
+
self->cleanupFunc = NULL;
|
312
|
+
self->parent = parent;
|
313
|
+
self->cleanupFunc = cleaner;
|
314
|
+
}
|
471
315
|
|
316
|
+
/*
|
317
|
+
* Adjusts the parent's reference count
|
318
|
+
*/
|
472
319
|
static
|
473
|
-
|
320
|
+
int add_child(nuodb_handle* parent, nuodb_handle* child)
|
474
321
|
{
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
322
|
+
parent->numUsed++;
|
323
|
+
|
324
|
+
return parent->numUsed;
|
325
|
+
}
|
326
|
+
|
327
|
+
/*
|
328
|
+
* Decrements the parent's reference count. Returns whether or not this child was the last one.
|
329
|
+
* If true, that means the responsibility for freeing the parent rests with the child handle
|
330
|
+
* calling this function.
|
331
|
+
*/
|
332
|
+
static
|
333
|
+
bool remove_from_parent(nuodb_handle* child, nuodb_handle* parent)
|
334
|
+
{
|
335
|
+
//parent may be NULL
|
336
|
+
if (parent) {
|
337
|
+
parent->numUsed--;
|
338
|
+
assert(parent->numUsed >= 0);
|
339
|
+
return parent->numUsed == 0 && parent->freePending;
|
493
340
|
}
|
494
|
-
|
341
|
+
|
342
|
+
return false;
|
495
343
|
}
|
496
344
|
|
345
|
+
/*
|
346
|
+
* Method attempts to free handle and recursively free its parent if necessary. Returns a pointer
|
347
|
+
* to any exception encoundered while executing cleanup functions. Errors do not stop recursion.
|
348
|
+
* An error in the child won't stop this from attempting to free the parent. To do otherwise would
|
349
|
+
* cause a leak.
|
350
|
+
*/
|
497
351
|
static
|
498
|
-
|
352
|
+
NuoDB::SQLException* handle_free(nuodb_handle* handle, nuodb_handle* parent)
|
499
353
|
{
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
354
|
+
if (handle->numUsed == 0) {
|
355
|
+
bool needToRemoveParent = remove_from_parent(handle, parent);
|
356
|
+
|
357
|
+
NuoDB::SQLException* caughtError = NULL;
|
358
|
+
|
359
|
+
try {
|
360
|
+
//clean up ourselves
|
361
|
+
handle->cleanupFunc(handle);
|
362
|
+
} catch (NuoDB::SQLException& err) {
|
363
|
+
caughtError = &err;
|
364
|
+
}
|
365
|
+
|
366
|
+
try {
|
367
|
+
//clean up parent if we're the last ones out
|
368
|
+
if (needToRemoveParent) {
|
369
|
+
handle_free(parent, parent->parent);
|
370
|
+
}
|
371
|
+
} catch (NuoDB::SQLException& err) {
|
372
|
+
if (!caughtError) {
|
373
|
+
caughtError = &err;
|
374
|
+
}
|
508
375
|
}
|
376
|
+
|
377
|
+
//free ourselves
|
378
|
+
trace("freeing object");
|
379
|
+
free(handle);
|
380
|
+
|
381
|
+
return caughtError;
|
382
|
+
} else {
|
383
|
+
handle->freePending = true;
|
384
|
+
return NULL;
|
509
385
|
}
|
510
386
|
}
|
511
387
|
|
512
388
|
static
|
513
|
-
void nuodb_result_mark(void
|
389
|
+
void nuodb_result_mark(void* ptr)
|
514
390
|
{
|
515
391
|
trace("nuodb_result_mark");
|
516
|
-
nuodb_result_handle
|
517
|
-
rb_gc_mark(handle->
|
392
|
+
nuodb_result_handle* handle = static_cast<nuodb_result_handle *>(ptr);
|
393
|
+
rb_gc_mark(handle->statement);
|
518
394
|
}
|
519
395
|
|
520
396
|
static
|
521
|
-
void
|
397
|
+
void nuodb_result_cleanup(nuodb_handle* handle)
|
522
398
|
{
|
523
|
-
|
524
|
-
|
399
|
+
nuodb_result_handle* resultHandle = (nuodb_result_handle*)handle;
|
400
|
+
|
401
|
+
if (resultHandle && resultHandle->pointer) {
|
402
|
+
resultHandle->pointer->close();
|
403
|
+
}
|
404
|
+
}
|
405
|
+
|
406
|
+
static
|
407
|
+
void nuodb_result_free(nuodb_handle* handle)
|
408
|
+
{
|
409
|
+
trace("nuodb_result_free");
|
410
|
+
nuodb_result_handle* result_handle = (nuodb_result_handle*)handle;
|
411
|
+
|
412
|
+
if (result_handle) {
|
413
|
+
NuoDB::SQLException* err = handle_free(handle, (result_handle->prepStmt != NULL ? (nuodb_handle*)result_handle->prepStmt : (nuodb_handle*)result_handle->stmt));
|
414
|
+
|
415
|
+
if (err) {
|
416
|
+
//Not ok to raise an error during GC
|
417
|
+
//rb_raise_nuodb_error(err->getSqlcode(), "Failed to successfully close result set: %s", err->getText());
|
418
|
+
log(ERROR, "Failed to successfully close result set");
|
419
|
+
log(ERROR, err->getText());
|
420
|
+
}
|
421
|
+
}
|
525
422
|
}
|
526
423
|
|
527
424
|
/*
|
@@ -534,49 +431,9 @@ static
|
|
534
431
|
VALUE nuodb_result_finish(VALUE self)
|
535
432
|
{
|
536
433
|
trace("nuodb_result_free_protect");
|
537
|
-
nuodb_result_handle
|
434
|
+
nuodb_result_handle* handle = cast_handle<nuodb_result_handle>(self);
|
538
435
|
nuodb_result_free(handle);
|
539
|
-
// if (handle != NULL)
|
540
|
-
// {
|
541
|
-
// if (handle->pointer != NULL)
|
542
|
-
// {
|
543
|
-
// try
|
544
|
-
// {
|
545
|
-
// //handle->pointer->close();
|
546
|
-
// //handle->pointer = NULL;
|
547
|
-
// }
|
548
|
-
// catch (SQLException & e)
|
549
|
-
// {
|
550
|
-
// rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close result: %s", e.getText());
|
551
|
-
// }
|
552
|
-
// }
|
553
|
-
// }
|
554
436
|
return Qnil;
|
555
|
-
//
|
556
|
-
//
|
557
|
-
//
|
558
|
-
// trace("nuodb_result_finish");
|
559
|
-
// if (ENABLE_CLOSE_HOOK)
|
560
|
-
// {
|
561
|
-
// //nuodb_result_decr_reference_count(cast_handle<nuodb_result_handle>(self));
|
562
|
-
// }
|
563
|
-
// nuodb_result_handle * handle = ;
|
564
|
-
// if (handle != NULL && handle->pointer != NULL)
|
565
|
-
// {
|
566
|
-
// if (ATOMIC_DEC(handle->atomic) == 0)
|
567
|
-
// {
|
568
|
-
// try
|
569
|
-
// {
|
570
|
-
// //handle->pointer->close();
|
571
|
-
// //handle->pointer = NULL;
|
572
|
-
// }
|
573
|
-
// catch (SQLException & e)
|
574
|
-
// {
|
575
|
-
// rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close result set: %s", e.getText());
|
576
|
-
// }
|
577
|
-
// }
|
578
|
-
// }
|
579
|
-
// return Qnil;
|
580
437
|
}
|
581
438
|
|
582
439
|
static
|
@@ -592,6 +449,10 @@ VALUE nuodb_map_sql_type(int type)
|
|
592
449
|
symbol = ID2SYM(rb_intern("integer"));
|
593
450
|
break;
|
594
451
|
|
452
|
+
case NUOSQL_BINARY:
|
453
|
+
symbol = ID2SYM(rb_intern("binary"));
|
454
|
+
break;
|
455
|
+
|
595
456
|
case NUOSQL_FLOAT:
|
596
457
|
case NUOSQL_DOUBLE:
|
597
458
|
symbol = ID2SYM(rb_intern("float"));
|
@@ -628,18 +489,16 @@ VALUE nuodb_map_sql_type(int type)
|
|
628
489
|
symbol = ID2SYM(rb_intern("numeric"));
|
629
490
|
break;
|
630
491
|
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
//
|
492
|
+
case NUOSQL_BLOB:
|
493
|
+
symbol = ID2SYM(rb_intern("blob"));
|
494
|
+
break;
|
635
495
|
// case NUOSQL_CLOB:
|
636
496
|
// symbol = ID2SYM(rb_intern("clob"));
|
637
497
|
// break;
|
638
498
|
|
639
499
|
case NUOSQL_NULL:
|
640
|
-
case NUOSQL_BLOB:
|
500
|
+
//case NUOSQL_BLOB:
|
641
501
|
case NUOSQL_CLOB:
|
642
|
-
case NUOSQL_BINARY:
|
643
502
|
case NUOSQL_LONGVARBINARY:
|
644
503
|
default:
|
645
504
|
rb_raise(rb_eNotImpError, "Unsupported SQL type: %d", type);
|
@@ -647,53 +506,51 @@ VALUE nuodb_map_sql_type(int type)
|
|
647
506
|
return symbol;
|
648
507
|
}
|
649
508
|
static
|
650
|
-
VALUE
|
651
|
-
{
|
652
|
-
trace("
|
653
|
-
nuodb_handle
|
654
|
-
if (parent_handle != NULL)
|
655
|
-
|
656
|
-
nuodb_result_handle
|
657
|
-
handle
|
658
|
-
handle->
|
659
|
-
handle
|
660
|
-
|
509
|
+
VALUE nuodb_result_init(VALUE parent, NuoDB::ResultSet* results, NuoDB::Connection* connection)
|
510
|
+
{
|
511
|
+
trace("nuodb_result_init");
|
512
|
+
nuodb_handle* parent_handle = cast_handle<nuodb_handle>(parent);
|
513
|
+
if (parent_handle != NULL) {
|
514
|
+
trace("alloc result set");
|
515
|
+
nuodb_result_handle* handle = ALLOC(struct nuodb_result_handle);
|
516
|
+
handle_init(handle, parent_handle, 0, nuodb_result_cleanup);
|
517
|
+
handle->statement = parent;
|
518
|
+
add_child(parent_handle, handle);
|
519
|
+
|
520
|
+
handle->prepStmt = NULL;
|
521
|
+
handle->stmt = NULL;
|
522
|
+
handle->columnCount = -1;
|
523
|
+
handle->types = NULL;
|
524
|
+
handle->resultMetaData = NULL;
|
661
525
|
handle->pointer = results;
|
662
526
|
handle->connection = connection;
|
663
|
-
|
664
|
-
VALUE self = Data_Wrap_Struct(nuodb_result_klass, nuodb_result_mark, nuodb_result_decr_reference_count, handle);
|
527
|
+
VALUE self = Data_Wrap_Struct(nuodb_result_klass, nuodb_result_mark, nuodb_result_free, handle);
|
665
528
|
|
666
529
|
rb_iv_set(self, "@columns", Qnil);
|
667
530
|
rb_iv_set(self, "@rows", Qnil);
|
668
531
|
|
669
532
|
if (!rb_block_given_p()) {
|
670
|
-
trace("
|
533
|
+
trace("nuodb_result_init: no block");
|
671
534
|
|
672
535
|
return self;
|
673
536
|
}
|
674
537
|
|
675
|
-
trace("
|
538
|
+
trace("nuodb_result_init: begin block");
|
676
539
|
|
677
540
|
int exception = 0;
|
678
541
|
VALUE result = rb_protect(rb_yield, self, &exception);
|
679
542
|
|
680
|
-
trace("
|
543
|
+
trace("nuodb_result_init: end block");
|
681
544
|
|
682
|
-
|
545
|
+
trace("nuodb_result_init: auto finish");
|
683
546
|
|
684
|
-
|
685
|
-
|
686
|
-
if (exception)
|
687
|
-
{
|
547
|
+
if (exception) {
|
548
|
+
//@TODO - don't we need to free here?
|
688
549
|
rb_jump_tag(exception);
|
689
|
-
}
|
690
|
-
else
|
691
|
-
{
|
550
|
+
} else {
|
692
551
|
return result;
|
693
552
|
}
|
694
|
-
}
|
695
|
-
else
|
696
|
-
{
|
553
|
+
} else {
|
697
554
|
rb_raise(rb_eArgError, "invalid state: statement handle nil");
|
698
555
|
}
|
699
556
|
return Qnil;
|
@@ -708,10 +565,9 @@ nuodb_get_rb_timezone_offset()
|
|
708
565
|
}
|
709
566
|
|
710
567
|
static VALUE
|
711
|
-
nuodb_get_rb_value(int column, SqlType type, ResultSet
|
568
|
+
nuodb_get_rb_value(int column, SqlType type, ResultSet* results)
|
712
569
|
{
|
713
570
|
VALUE value = Qnil;
|
714
|
-
|
715
571
|
switch (type)
|
716
572
|
{
|
717
573
|
case NUOSQL_BIT:
|
@@ -764,11 +620,13 @@ nuodb_get_rb_value(int column, SqlType type, ResultSet * results)
|
|
764
620
|
}
|
765
621
|
break;
|
766
622
|
}
|
767
|
-
|
623
|
+
|
624
|
+
case NUOSQL_BLOB:
|
625
|
+
case NUOSQL_BINARY:
|
768
626
|
case NUOSQL_VARCHAR:
|
769
627
|
case NUOSQL_LONGVARCHAR:
|
770
628
|
{
|
771
|
-
char const
|
629
|
+
char const* field = results->getString(column);
|
772
630
|
if (!results->wasNull())
|
773
631
|
{
|
774
632
|
value = rb_str_new2(field);
|
@@ -777,7 +635,7 @@ nuodb_get_rb_value(int column, SqlType type, ResultSet * results)
|
|
777
635
|
}
|
778
636
|
case NUOSQL_DATE:
|
779
637
|
{
|
780
|
-
NuoDB::Date
|
638
|
+
NuoDB::Date* field = results->getDate(column);
|
781
639
|
if (!results->wasNull())
|
782
640
|
{
|
783
641
|
double secs = (double) field->getSeconds();
|
@@ -789,17 +647,17 @@ nuodb_get_rb_value(int column, SqlType type, ResultSet * results)
|
|
789
647
|
case NUOSQL_TIME:
|
790
648
|
case NUOSQL_TIMESTAMP:
|
791
649
|
{
|
792
|
-
NuoDB::Timestamp
|
650
|
+
NuoDB::Timestamp* field = results->getTimestamp(column);
|
793
651
|
if (!results->wasNull())
|
794
652
|
{
|
795
|
-
double secs = ((double) field->getSeconds()) + (((double) field->getNanos()) /
|
653
|
+
double secs = ((double) field->getSeconds()) + (((double) field->getNanos()) / NANOS_PER_SECOND);
|
796
654
|
value = rb_funcall(rb_cTime, rb_intern("at"), 1, rb_float_new(secs)); // - nuodb_get_rb_timezone_offset()
|
797
655
|
}
|
798
656
|
break;
|
799
657
|
}
|
800
658
|
case NUOSQL_NUMERIC:
|
801
659
|
{
|
802
|
-
char const
|
660
|
+
char const* field = results->getString(column);
|
803
661
|
if (!results->wasNull())
|
804
662
|
{
|
805
663
|
rb_require("bigdecimal");
|
@@ -812,13 +670,23 @@ nuodb_get_rb_value(int column, SqlType type, ResultSet * results)
|
|
812
670
|
}
|
813
671
|
default:
|
814
672
|
{
|
815
|
-
rb_raise(rb_eTypeError, "
|
673
|
+
rb_raise(rb_eTypeError, "Not a supported ruby type: %d", type);
|
816
674
|
break;
|
817
675
|
}
|
818
676
|
}
|
819
677
|
return value;
|
820
678
|
}
|
821
679
|
|
680
|
+
static
|
681
|
+
NuoDB::ResultSetMetaData* getResultMetadata(nuodb_result_handle* result_handle)
|
682
|
+
{
|
683
|
+
if (!result_handle->resultMetaData && result_handle->pointer) {
|
684
|
+
result_handle->resultMetaData = result_handle->pointer->getMetaData();
|
685
|
+
}
|
686
|
+
|
687
|
+
return result_handle->resultMetaData;
|
688
|
+
}
|
689
|
+
|
822
690
|
/*
|
823
691
|
* call-seq:
|
824
692
|
* result.columns -> ary
|
@@ -835,53 +703,26 @@ static VALUE
|
|
835
703
|
nuodb_result_columns(VALUE self)
|
836
704
|
{
|
837
705
|
trace("nuodb_result_columns");
|
838
|
-
nuodb_result_handle
|
839
|
-
if (handle != NULL && handle->pointer != NULL)
|
840
|
-
{
|
706
|
+
nuodb_result_handle* handle = cast_handle<nuodb_result_handle>(self);
|
707
|
+
if (handle != NULL && handle->pointer != NULL) {
|
841
708
|
VALUE columns = rb_iv_get(self, "@columns");
|
842
|
-
|
843
|
-
{
|
844
|
-
try
|
845
|
-
|
846
|
-
ResultSetMetaData * result_metadata = handle->pointer->getMetaData();
|
847
|
-
DatabaseMetaData * database_metadata = handle->connection->getMetaData();
|
709
|
+
|
710
|
+
if (NIL_P(columns)) {
|
711
|
+
try {
|
712
|
+
ResultSetMetaData* result_metadata = getResultMetadata(handle);
|
848
713
|
|
849
714
|
VALUE array = rb_ary_new();
|
850
715
|
rb_require("nuodb/column");
|
851
716
|
VALUE column_klass = rb_const_get(m_nuodb, rb_intern("Column"));
|
852
717
|
|
853
718
|
int column_count = result_metadata->getColumnCount();
|
854
|
-
for (int column_index = 1; column_index < column_count + 1; ++column_index)
|
855
|
-
{
|
856
|
-
char const * schema_name = result_metadata->getSchemaName(column_index);
|
857
|
-
char const * table_name = result_metadata->getTableName(column_index);
|
858
|
-
char const * column_name = result_metadata->getColumnName(column_index);
|
859
|
-
|
860
|
-
// args: [name, default, sql_type, null]
|
719
|
+
for (int column_index = 1; column_index < column_count + 1; ++column_index) {
|
861
720
|
VALUE args[4];
|
862
721
|
|
863
722
|
args[0] = rb_str_new2(result_metadata->getColumnLabel(column_index));
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
if(database_metadata_results->next())
|
869
|
-
{
|
870
|
-
try
|
871
|
-
{
|
872
|
-
args[1] = nuodb_get_rb_value(database_metadata_results->findColumn("COLUMN_DEF"),
|
873
|
-
(SqlType) result_metadata->getColumnType(column_index), database_metadata_results);
|
874
|
-
}
|
875
|
-
catch (SQLException & e)
|
876
|
-
{
|
877
|
-
args[1] = Qnil;
|
878
|
-
}
|
879
|
-
}
|
880
|
-
else
|
881
|
-
{
|
882
|
-
args[1] = Qnil;
|
883
|
-
}
|
884
|
-
database_metadata_results->close();
|
723
|
+
|
724
|
+
//Can't issue database metadata queries as that will close out the current transaction due to a bug
|
725
|
+
args[1] = Qnil;
|
885
726
|
|
886
727
|
args[2] = nuodb_map_sql_type(result_metadata->getColumnType(column_index));
|
887
728
|
args[3] = result_metadata->isNullable(column_index) ? Qtrue : Qfalse;
|
@@ -893,24 +734,40 @@ nuodb_result_columns(VALUE self)
|
|
893
734
|
rb_iv_set(self, "@columns", array);
|
894
735
|
|
895
736
|
return array;
|
896
|
-
}
|
897
|
-
catch (SQLException & e)
|
898
|
-
{
|
737
|
+
} catch (SQLException & e) {
|
899
738
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to create column info: %s", e.getText());
|
900
739
|
}
|
901
|
-
}
|
902
|
-
else
|
903
|
-
{
|
740
|
+
} else {
|
904
741
|
return columns;
|
905
742
|
}
|
906
|
-
}
|
907
|
-
else
|
908
|
-
{
|
743
|
+
} else {
|
909
744
|
rb_raise(rb_eArgError, "invalid state: result handle nil");
|
910
745
|
}
|
911
746
|
return Qnil;
|
912
747
|
}
|
913
748
|
|
749
|
+
static
|
750
|
+
void nuodb_populate_row_metadata(nuodb_result_handle* result_handle)
|
751
|
+
{
|
752
|
+
if (!result_handle->pointer || result_handle->types != NULL) {
|
753
|
+
return;
|
754
|
+
}
|
755
|
+
trace("populating row metadata");
|
756
|
+
|
757
|
+
NuoDB::ResultSetMetaData* metadata = getResultMetadata(result_handle);
|
758
|
+
assert(metadata != NULL);
|
759
|
+
|
760
|
+
int32_t column_count = metadata->getColumnCount();
|
761
|
+
result_handle->columnCount = column_count;
|
762
|
+
result_handle->types = ALLOC_N(SqlType, column_count);
|
763
|
+
|
764
|
+
for (int32_t column = 1; column < column_count + 1; column++) {
|
765
|
+
SqlType type = (SqlType) metadata->getColumnType(column);
|
766
|
+
result_handle->types[column-1] = type;
|
767
|
+
}
|
768
|
+
|
769
|
+
}
|
770
|
+
|
914
771
|
/*
|
915
772
|
* call-seq:
|
916
773
|
* result.rows -> ary
|
@@ -932,25 +789,24 @@ static VALUE
|
|
932
789
|
nuodb_result_rows(VALUE self)
|
933
790
|
{
|
934
791
|
trace("nuodb_result_rows");
|
935
|
-
nuodb_result_handle
|
936
|
-
|
937
|
-
{
|
792
|
+
nuodb_result_handle* handle = cast_handle<nuodb_result_handle>(self);
|
793
|
+
|
794
|
+
if (handle != NULL && handle->pointer != NULL) {
|
795
|
+
|
938
796
|
VALUE rows = rb_iv_get(self, "@rows");
|
939
|
-
|
940
|
-
{
|
941
|
-
try
|
942
|
-
|
797
|
+
|
798
|
+
if (NIL_P(rows)) {
|
799
|
+
try {
|
800
|
+
nuodb_populate_row_metadata(handle);
|
943
801
|
rows = rb_ary_new();
|
944
802
|
|
945
|
-
while (handle->pointer->next())
|
946
|
-
|
803
|
+
while (handle->pointer->next()) {
|
804
|
+
|
947
805
|
VALUE row = rb_ary_new();
|
948
806
|
|
949
|
-
|
950
|
-
int32_t
|
951
|
-
|
952
|
-
{
|
953
|
-
SqlType type = (SqlType) metadata->getColumnType(column);
|
807
|
+
//remember, SQL result set columns are 1-indexed
|
808
|
+
for (int32_t column = 1; column < handle->columnCount + 1; column++) {
|
809
|
+
SqlType type = handle->types[column - 1];
|
954
810
|
rb_ary_push(row, nuodb_get_rb_value(column, type, handle->pointer));
|
955
811
|
}
|
956
812
|
|
@@ -958,16 +814,12 @@ nuodb_result_rows(VALUE self)
|
|
958
814
|
}
|
959
815
|
|
960
816
|
rb_iv_set(self, "@rows", rows);
|
961
|
-
}
|
962
|
-
catch (SQLException & e)
|
963
|
-
{
|
817
|
+
} catch (SQLException & e) {
|
964
818
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to create a rows array: %s", e.getText());
|
965
819
|
}
|
966
820
|
}
|
967
821
|
return rows;
|
968
|
-
}
|
969
|
-
else
|
970
|
-
{
|
822
|
+
} else {
|
971
823
|
rb_raise(rb_eArgError, "invalid state: result handle nil");
|
972
824
|
}
|
973
825
|
return Qnil;
|
@@ -992,7 +844,7 @@ static VALUE
|
|
992
844
|
nuodb_result_each(VALUE self)
|
993
845
|
{
|
994
846
|
trace("nuodb_result_each");
|
995
|
-
nuodb_result_handle
|
847
|
+
nuodb_result_handle* handle = cast_handle<nuodb_result_handle>(self);
|
996
848
|
if (handle != NULL && handle->pointer != NULL)
|
997
849
|
{
|
998
850
|
VALUE rows = rb_iv_get(self, "@rows");
|
@@ -1038,59 +890,43 @@ void nuodb_define_result_api()
|
|
1038
890
|
//------------------------------------------------------------------------------
|
1039
891
|
|
1040
892
|
static
|
1041
|
-
|
893
|
+
void nuodb_statement_mark(void* ptr)
|
1042
894
|
{
|
1043
|
-
trace("
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
if (handle->pointer != NULL)
|
1048
|
-
{
|
1049
|
-
try
|
1050
|
-
{
|
1051
|
-
log(INFO, "closing statement");
|
1052
|
-
handle->pointer->close();
|
1053
|
-
handle->pointer = NULL;
|
1054
|
-
}
|
1055
|
-
catch (SQLException & e)
|
1056
|
-
{
|
1057
|
-
rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close statement: %s", e.getText());
|
1058
|
-
}
|
1059
|
-
}
|
1060
|
-
}
|
1061
|
-
return Qnil;
|
895
|
+
trace("nuodb_statement_mark");
|
896
|
+
|
897
|
+
nuodb_statement_handle* handle = static_cast<nuodb_statement_handle *>(ptr);
|
898
|
+
rb_gc_mark(handle->connection);
|
1062
899
|
}
|
1063
900
|
|
1064
901
|
static
|
1065
|
-
void nuodb_statement_free(void
|
902
|
+
void nuodb_statement_free(void* ptr)
|
1066
903
|
{
|
1067
904
|
trace("nuodb_statement_free");
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
{
|
1074
|
-
|
905
|
+
nuodb_statement_handle* handle = (nuodb_statement_handle*)ptr;
|
906
|
+
|
907
|
+
if (handle && handle->pointer) {
|
908
|
+
NuoDB::SQLException* err = handle_free(handle, handle->connection_handle);
|
909
|
+
|
910
|
+
if (err) {
|
911
|
+
//Not ok to raise an error during GC
|
912
|
+
//rb_raise_nuodb_error(err->getSqlcode(), "Failed to successfully close statement: %s", err->getText());
|
913
|
+
log(ERROR, "Failed to successfully close statement");
|
914
|
+
log(ERROR, err->getText());
|
1075
915
|
}
|
1076
916
|
}
|
917
|
+
|
1077
918
|
}
|
1078
919
|
|
1079
920
|
static
|
1080
|
-
void
|
921
|
+
void nuodb_statement_cleanup(nuodb_handle* handle)
|
1081
922
|
{
|
1082
|
-
|
923
|
+
nuodb_statement_handle* statementHandle = (nuodb_statement_handle*)handle;
|
1083
924
|
|
1084
|
-
|
1085
|
-
|
925
|
+
if (statementHandle && statementHandle->pointer) {
|
926
|
+
statementHandle->pointer->close();
|
927
|
+
}
|
1086
928
|
}
|
1087
929
|
|
1088
|
-
static
|
1089
|
-
void nuodb_statement_decr_reference_count(void * ptr)
|
1090
|
-
{
|
1091
|
-
trace("nuodb_statement_decr_reference_count");
|
1092
|
-
decr_reference_count(static_cast<nuodb_statement_handle *>(ptr));
|
1093
|
-
}
|
1094
930
|
|
1095
931
|
/*
|
1096
932
|
* call-seq:
|
@@ -1102,39 +938,9 @@ static
|
|
1102
938
|
VALUE nuodb_statement_finish(VALUE self)
|
1103
939
|
{
|
1104
940
|
trace("nuodb_statement_finish");
|
1105
|
-
nuodb_statement_handle
|
941
|
+
nuodb_statement_handle* handle = cast_handle<nuodb_statement_handle>(self);//reinterpret_cast<nuodb_statement_handle*>(value);
|
1106
942
|
nuodb_statement_free(handle);
|
1107
|
-
// if (handle != NULL)
|
1108
|
-
// {
|
1109
|
-
// if (handle->pointer != NULL)
|
1110
|
-
// {
|
1111
|
-
// try
|
1112
|
-
// {
|
1113
|
-
// log(INFO, "closing statement");
|
1114
|
-
// handle->pointer->close();
|
1115
|
-
// handle->pointer = NULL;
|
1116
|
-
// }
|
1117
|
-
// catch (SQLException & e)
|
1118
|
-
// {
|
1119
|
-
// rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close statement: %s", e.getText());
|
1120
|
-
// }
|
1121
|
-
// }
|
1122
|
-
// }
|
1123
943
|
return Qnil;
|
1124
|
-
//
|
1125
|
-
// if (ENABLE_CLOSE_HOOK)
|
1126
|
-
// {
|
1127
|
-
// nuodb_statement_handle * handle = cast_handle<nuodb_statement_handle>(self);
|
1128
|
-
// if (handle != NULL && handle->pointer != NULL)
|
1129
|
-
// {
|
1130
|
-
// nuodb_statement_decr_reference_count(handle);
|
1131
|
-
// }
|
1132
|
-
// else
|
1133
|
-
// {
|
1134
|
-
// rb_raise(rb_eArgError, "invalid state: statement handle nil");
|
1135
|
-
// }
|
1136
|
-
// }
|
1137
|
-
// return Qnil;
|
1138
944
|
}
|
1139
945
|
|
1140
946
|
static
|
@@ -1142,33 +948,28 @@ VALUE nuodb_statement_initialize(VALUE parent)
|
|
1142
948
|
{
|
1143
949
|
trace("nuodb_statement_initialize");
|
1144
950
|
|
1145
|
-
nuodb_connection_handle
|
1146
|
-
|
1147
|
-
{
|
1148
|
-
NuoDB::Statement
|
1149
|
-
try
|
1150
|
-
{
|
951
|
+
nuodb_connection_handle* parent_handle = cast_handle<nuodb_connection_handle>(parent);
|
952
|
+
|
953
|
+
if (parent_handle != NULL && parent_handle->pointer != NULL) {
|
954
|
+
NuoDB::Statement* statement = NULL;
|
955
|
+
try {
|
1151
956
|
statement = parent_handle->pointer->createStatement();
|
1152
|
-
}
|
1153
|
-
catch (SQLException & e)
|
1154
|
-
{
|
957
|
+
} catch (SQLException & e) {
|
1155
958
|
log(ERROR, "rb_raise");
|
1156
959
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to create statement: %s", e.getText());
|
1157
960
|
}
|
1158
961
|
|
1159
|
-
|
962
|
+
trace("alloc");
|
963
|
+
nuodb_statement_handle* handle = ALLOC(nuodb_statement_handle);
|
964
|
+
handle_init(handle, parent_handle, 1, nuodb_statement_cleanup);
|
965
|
+
add_child(parent_handle, handle);
|
1160
966
|
|
1161
|
-
handle->
|
1162
|
-
handle->
|
1163
|
-
handle->parent = parent;
|
1164
|
-
handle->parent_handle = parent_handle;
|
967
|
+
handle->connection = parent;
|
968
|
+
handle->connection_handle = parent_handle;
|
1165
969
|
handle->pointer = statement;
|
1166
|
-
|
1167
|
-
assert(handle->atomic = 1);
|
1168
|
-
VALUE self = Data_Wrap_Struct(nuodb_statement_klass, nuodb_statement_mark, nuodb_statement_decr_reference_count, handle);
|
970
|
+
VALUE self = Data_Wrap_Struct(nuodb_statement_klass, nuodb_statement_mark, nuodb_statement_free, handle);
|
1169
971
|
if (!rb_block_given_p()) {
|
1170
972
|
trace("nuodb_statement_initialize: no block");
|
1171
|
-
track_ref_count("ALLOC STMT S", cast_handle<nuodb_handle>(self));
|
1172
973
|
return self;
|
1173
974
|
}
|
1174
975
|
|
@@ -1184,17 +985,13 @@ VALUE nuodb_statement_initialize(VALUE parent)
|
|
1184
985
|
|
1185
986
|
trace("nuodb_statement_initialize: auto finish");
|
1186
987
|
|
1187
|
-
if (exception)
|
1188
|
-
|
988
|
+
if (exception) {
|
989
|
+
//@TODO - don't we need to free memory here?
|
1189
990
|
rb_jump_tag(exception);
|
1190
|
-
}
|
1191
|
-
else
|
1192
|
-
{
|
991
|
+
} else {
|
1193
992
|
return result;
|
1194
993
|
}
|
1195
|
-
}
|
1196
|
-
else
|
1197
|
-
{
|
994
|
+
} else {
|
1198
995
|
rb_raise(rb_eArgError, "invalid state: statement handle nil");
|
1199
996
|
}
|
1200
997
|
return Qnil;
|
@@ -1218,7 +1015,7 @@ VALUE nuodb_statement_execute(VALUE self, VALUE sql)
|
|
1218
1015
|
rb_raise(rb_eTypeError, "wrong sql argument type %s (String expected)", rb_class2name(CLASS_OF(sql)));
|
1219
1016
|
}
|
1220
1017
|
|
1221
|
-
nuodb_statement_handle
|
1018
|
+
nuodb_statement_handle* handle = cast_handle<nuodb_statement_handle>(self);
|
1222
1019
|
if (handle != NULL && handle->pointer != NULL)
|
1223
1020
|
{
|
1224
1021
|
try
|
@@ -1249,7 +1046,7 @@ VALUE nuodb_statement_update_count(VALUE self)
|
|
1249
1046
|
{
|
1250
1047
|
trace("nuodb_statement_update_count");
|
1251
1048
|
|
1252
|
-
nuodb_statement_handle
|
1049
|
+
nuodb_statement_handle* handle = cast_handle<nuodb_statement_handle>(self);
|
1253
1050
|
if (handle != NULL && handle->pointer != NULL)
|
1254
1051
|
{
|
1255
1052
|
try
|
@@ -1278,12 +1075,20 @@ static VALUE nuodb_statement_results(VALUE self)
|
|
1278
1075
|
{
|
1279
1076
|
trace("nuodb_statement_results");
|
1280
1077
|
|
1281
|
-
nuodb_statement_handle
|
1078
|
+
nuodb_statement_handle* handle = cast_handle<nuodb_statement_handle>(self);
|
1282
1079
|
if (handle != NULL && handle->pointer != NULL)
|
1283
1080
|
{
|
1284
1081
|
try
|
1285
1082
|
{
|
1286
|
-
|
1083
|
+
VALUE ruby_handle = nuodb_result_init(self, handle->pointer->getResultSet(), handle->pointer->getConnection());
|
1084
|
+
nuodb_result_handle* our_result_handle = cast_handle<nuodb_result_handle>(ruby_handle);
|
1085
|
+
|
1086
|
+
assert(our_result_handle != NULL);
|
1087
|
+
assert(our_result_handle->prepStmt == NULL);
|
1088
|
+
assert(our_result_handle->stmt == NULL);
|
1089
|
+
|
1090
|
+
our_result_handle->stmt = handle;
|
1091
|
+
return ruby_handle;
|
1287
1092
|
}
|
1288
1093
|
catch (SQLException & e)
|
1289
1094
|
{
|
@@ -1308,26 +1113,27 @@ static VALUE nuodb_statement_generated_keys(VALUE self)
|
|
1308
1113
|
{
|
1309
1114
|
trace("nuodb_statement_generated_keys");
|
1310
1115
|
|
1311
|
-
nuodb_statement_handle
|
1312
|
-
if (handle != NULL && handle->pointer != NULL)
|
1313
|
-
|
1314
|
-
try
|
1315
|
-
{
|
1116
|
+
nuodb_statement_handle* handle = cast_handle<nuodb_statement_handle>(self);
|
1117
|
+
if (handle != NULL && handle->pointer != NULL) {
|
1118
|
+
try {
|
1316
1119
|
// this hack should not have been necessary; it should never have
|
1317
1120
|
// returned null, this is a product defect.
|
1318
|
-
ResultSet
|
1319
|
-
if (results != NULL)
|
1320
|
-
|
1321
|
-
|
1121
|
+
ResultSet* results = handle->pointer->getGeneratedKeys();
|
1122
|
+
if (results != NULL) {
|
1123
|
+
VALUE ruby_handle = nuodb_result_init(self, results, handle->pointer->getConnection());
|
1124
|
+
nuodb_result_handle* our_result_handle = cast_handle<nuodb_result_handle>(ruby_handle);
|
1125
|
+
|
1126
|
+
assert(our_result_handle != NULL);
|
1127
|
+
assert(our_result_handle->prepStmt == NULL);
|
1128
|
+
assert(our_result_handle->stmt == NULL);
|
1129
|
+
|
1130
|
+
our_result_handle->stmt = handle;
|
1131
|
+
return ruby_handle;
|
1322
1132
|
}
|
1323
|
-
}
|
1324
|
-
catch (SQLException & e)
|
1325
|
-
{
|
1133
|
+
} catch (SQLException & e) {
|
1326
1134
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to get the generated keys for the statement: %s", e.getText());
|
1327
1135
|
}
|
1328
|
-
}
|
1329
|
-
else
|
1330
|
-
{
|
1136
|
+
} else {
|
1331
1137
|
rb_raise(rb_eArgError, "invalid state: statement handle nil");
|
1332
1138
|
}
|
1333
1139
|
return Qnil;
|
@@ -1360,60 +1166,40 @@ void nuodb_define_statement_api()
|
|
1360
1166
|
//------------------------------------------------------------------------------
|
1361
1167
|
|
1362
1168
|
static
|
1363
|
-
|
1169
|
+
void nuodb_prepared_statement_free(void* ptr)
|
1364
1170
|
{
|
1365
|
-
trace("
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
{
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
handle->pointer = NULL;
|
1377
|
-
}
|
1378
|
-
catch (SQLException & e)
|
1379
|
-
{
|
1380
|
-
rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close statement: %s", e.getText());
|
1381
|
-
}
|
1171
|
+
trace("nuodb_prepared_statement_free");
|
1172
|
+
|
1173
|
+
if (ptr != NULL) {
|
1174
|
+
nuodb_prepared_statement_handle* handle = (nuodb_prepared_statement_handle*)ptr;
|
1175
|
+
NuoDB::SQLException* err = handle_free(handle, handle->connection_handle);
|
1176
|
+
|
1177
|
+
if (err) {
|
1178
|
+
//Not ok to raise a ruby error during GC
|
1179
|
+
//rb_raise_nuodb_error(err->getSqlcode(), "Failed to successfully close prepared statement: %s", err->getText());
|
1180
|
+
log(ERROR, "Failed to successfully close prepared statement");
|
1181
|
+
log(ERROR, err->getText());
|
1382
1182
|
}
|
1383
1183
|
}
|
1384
|
-
return Qnil;
|
1385
1184
|
}
|
1386
1185
|
|
1387
1186
|
static
|
1388
|
-
void
|
1187
|
+
void nuodb_prepared_statement_cleanup(nuodb_handle* handle)
|
1389
1188
|
{
|
1390
|
-
|
1189
|
+
nuodb_prepared_statement_handle* prepHandle = (nuodb_prepared_statement_handle*)prepHandle;
|
1391
1190
|
|
1392
|
-
if (
|
1393
|
-
|
1394
|
-
int exception = 0;
|
1395
|
-
rb_protect(nuodb_prepared_statement_free_protect, reinterpret_cast<VALUE>(ptr), &exception);
|
1396
|
-
if (exception)
|
1397
|
-
{
|
1398
|
-
rb_jump_tag(exception);
|
1399
|
-
}
|
1191
|
+
if (prepHandle && prepHandle->pointer) {
|
1192
|
+
prepHandle->pointer->close();
|
1400
1193
|
}
|
1401
1194
|
}
|
1402
1195
|
|
1403
1196
|
static
|
1404
|
-
void nuodb_prepared_statement_mark(void
|
1197
|
+
void nuodb_prepared_statement_mark(void* ptr)
|
1405
1198
|
{
|
1406
1199
|
trace("nuodb_prepared_statement_mark");
|
1407
1200
|
|
1408
|
-
nuodb_prepared_statement_handle
|
1409
|
-
rb_gc_mark(handle->
|
1410
|
-
}
|
1411
|
-
|
1412
|
-
static
|
1413
|
-
void nuodb_prepared_statement_decr_reference_count(nuodb_handle * handle)
|
1414
|
-
{
|
1415
|
-
trace("nuodb_prepared_statement_decr_reference_count");
|
1416
|
-
decr_reference_count(handle);
|
1201
|
+
nuodb_prepared_statement_handle* handle = (nuodb_prepared_statement_handle *)ptr;
|
1202
|
+
rb_gc_mark(handle->connection);
|
1417
1203
|
}
|
1418
1204
|
|
1419
1205
|
/*
|
@@ -1426,41 +1212,9 @@ static
|
|
1426
1212
|
VALUE nuodb_prepared_statement_finish(VALUE self)
|
1427
1213
|
{
|
1428
1214
|
trace("nuodb_prepared_statement_finish");
|
1429
|
-
nuodb_prepared_statement_handle
|
1430
|
-
track_ref_count("FINISH PSTMT", handle);
|
1215
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);//reinterpret_cast<nuodb_prepared_statement_handle *>(value);
|
1431
1216
|
nuodb_prepared_statement_free(handle);
|
1432
|
-
// if (handle != NULL)
|
1433
|
-
// {
|
1434
|
-
// if (handle->pointer != NULL)
|
1435
|
-
// {
|
1436
|
-
// try
|
1437
|
-
// {
|
1438
|
-
// track_ref_count("CLOSE PSTMT", handle);
|
1439
|
-
// log(INFO, "closing prepared statement");
|
1440
|
-
// handle->pointer->close();
|
1441
|
-
// handle->pointer = NULL;
|
1442
|
-
// }
|
1443
|
-
// catch (SQLException & e)
|
1444
|
-
// {
|
1445
|
-
// rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close statement: %s", e.getText());
|
1446
|
-
// }
|
1447
|
-
// }
|
1448
|
-
// }
|
1449
1217
|
return Qnil;
|
1450
|
-
//
|
1451
|
-
// if (ENABLE_CLOSE_HOOK)
|
1452
|
-
// {
|
1453
|
-
// nuodb_prepared_statement_handle * handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1454
|
-
// if (handle != NULL && handle->pointer != NULL)
|
1455
|
-
// {
|
1456
|
-
// nuodb_prepared_statement_decr_reference_count(handle);
|
1457
|
-
// }
|
1458
|
-
// else
|
1459
|
-
// {
|
1460
|
-
// rb_raise(rb_eArgError, "invalid state: prepared statement handle nil");
|
1461
|
-
// }
|
1462
|
-
// }
|
1463
|
-
// return Qnil;
|
1464
1218
|
}
|
1465
1219
|
|
1466
1220
|
static
|
@@ -1468,34 +1222,30 @@ VALUE nuodb_prepared_statement_initialize(VALUE parent, VALUE sql)
|
|
1468
1222
|
{
|
1469
1223
|
trace("nuodb_prepared_statement_initialize");
|
1470
1224
|
|
1471
|
-
if (TYPE(sql) != T_STRING)
|
1472
|
-
{
|
1225
|
+
if (TYPE(sql) != T_STRING) {
|
1473
1226
|
rb_raise(rb_eTypeError, "wrong sql argument type %s (String expected)", rb_class2name(CLASS_OF(sql)));
|
1474
1227
|
}
|
1475
1228
|
|
1476
|
-
nuodb_connection_handle
|
1477
|
-
|
1478
|
-
{
|
1479
|
-
NuoDB::PreparedStatement
|
1480
|
-
try
|
1481
|
-
{
|
1229
|
+
nuodb_connection_handle* parent_handle = cast_handle<nuodb_connection_handle>(parent);
|
1230
|
+
|
1231
|
+
if (parent_handle != NULL && parent_handle->pointer != NULL) {
|
1232
|
+
NuoDB::PreparedStatement* statement = NULL;
|
1233
|
+
try {
|
1482
1234
|
statement = parent_handle->pointer->prepareStatement(StringValueCStr(sql),
|
1483
1235
|
NuoDB::RETURN_GENERATED_KEYS);
|
1484
|
-
}
|
1485
|
-
catch (SQLException & e)
|
1486
|
-
{
|
1236
|
+
} catch (SQLException & e) {
|
1487
1237
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to create prepared statement (%s): %s", sql, e.getText());
|
1488
1238
|
}
|
1489
1239
|
|
1490
|
-
|
1491
|
-
handle
|
1492
|
-
handle
|
1493
|
-
handle
|
1494
|
-
|
1240
|
+
trace("alloc");
|
1241
|
+
nuodb_prepared_statement_handle* handle = ALLOC(struct nuodb_prepared_statement_handle);
|
1242
|
+
handle_init(handle, parent_handle, 1, nuodb_prepared_statement_cleanup);
|
1243
|
+
add_child(parent_handle, handle);
|
1244
|
+
|
1245
|
+
handle->connection = parent;
|
1246
|
+
handle->connection_handle = parent_handle;
|
1495
1247
|
handle->pointer = statement;
|
1496
|
-
|
1497
|
-
assert(handle->atomic == 1);
|
1498
|
-
VALUE self = Data_Wrap_Struct(nuodb_prepared_statement_klass, nuodb_prepared_statement_mark, nuodb_prepared_statement_decr_reference_count, handle);
|
1248
|
+
VALUE self = Data_Wrap_Struct(nuodb_prepared_statement_klass, nuodb_prepared_statement_mark, nuodb_prepared_statement_free, handle);
|
1499
1249
|
|
1500
1250
|
if (!rb_block_given_p()) {
|
1501
1251
|
trace("nuodb_prepared_statement_initialize: no block");
|
@@ -1515,24 +1265,20 @@ VALUE nuodb_prepared_statement_initialize(VALUE parent, VALUE sql)
|
|
1515
1265
|
|
1516
1266
|
trace("nuodb_prepared_statement_initialize: auto finish");
|
1517
1267
|
|
1518
|
-
if (exception)
|
1519
|
-
|
1268
|
+
if (exception) {
|
1269
|
+
//@TODO - don't we have to free memory?
|
1520
1270
|
rb_jump_tag(exception);
|
1521
|
-
}
|
1522
|
-
else
|
1523
|
-
{
|
1271
|
+
} else {
|
1524
1272
|
return result;
|
1525
1273
|
}
|
1526
|
-
}
|
1527
|
-
else
|
1528
|
-
{
|
1274
|
+
} else {
|
1529
1275
|
rb_raise(rb_eArgError, "invalid state: prepared statement handle nil");
|
1530
1276
|
}
|
1531
1277
|
return Qnil;
|
1532
1278
|
}
|
1533
1279
|
|
1534
1280
|
static
|
1535
|
-
void raise_unsupported_type_at_index(char const
|
1281
|
+
void raise_unsupported_type_at_index(char const* type_name, int32_t index)
|
1536
1282
|
{
|
1537
1283
|
rb_raise(rb_eTypeError, "unsupported type %s at %d", type_name, index);
|
1538
1284
|
}
|
@@ -1559,7 +1305,7 @@ VALUE nuodb_prepared_statement_bind_param(VALUE self, VALUE param, VALUE value)
|
|
1559
1305
|
}
|
1560
1306
|
int32_t index = NUM2UINT(param);
|
1561
1307
|
|
1562
|
-
NuoDB::PreparedStatement
|
1308
|
+
NuoDB::PreparedStatement* statement = cast_pointer_member<
|
1563
1309
|
nuodb_prepared_statement_handle, NuoDB::PreparedStatement>(self);
|
1564
1310
|
|
1565
1311
|
try
|
@@ -1576,7 +1322,7 @@ VALUE nuodb_prepared_statement_bind_param(VALUE self, VALUE param, VALUE value)
|
|
1576
1322
|
case T_STRING: // 0x05
|
1577
1323
|
{
|
1578
1324
|
log(DEBUG, "supported: T_STRING");
|
1579
|
-
char const
|
1325
|
+
char const* real_value = RSTRING_PTR(value);
|
1580
1326
|
statement->setString(index, real_value);
|
1581
1327
|
}
|
1582
1328
|
break;
|
@@ -1614,7 +1360,7 @@ VALUE nuodb_prepared_statement_bind_param(VALUE self, VALUE param, VALUE value)
|
|
1614
1360
|
VALUE sec = rb_funcall(value, rb_intern("tv_sec"), 0);
|
1615
1361
|
//VALUE offset = rb_funcall(value, rb_intern("utc_offset"), 0);
|
1616
1362
|
VALUE usec = rb_funcall(value, rb_intern("tv_usec"), 0);
|
1617
|
-
SqlTimestamp sqlTimestamp(NUM2INT(sec), NUM2INT(usec) *
|
1363
|
+
SqlTimestamp sqlTimestamp(NUM2INT(sec), NUM2INT(usec) * NANOS_PER_MICRO); // + NUM2INT(offset)
|
1618
1364
|
statement->setTimestamp(index, &sqlTimestamp);
|
1619
1365
|
break;
|
1620
1366
|
}
|
@@ -1626,7 +1372,7 @@ VALUE nuodb_prepared_statement_bind_param(VALUE self, VALUE param, VALUE value)
|
|
1626
1372
|
VALUE sec = rb_funcall(time, rb_intern("tv_sec"), 0);
|
1627
1373
|
//VALUE offset = rb_funcall(time, rb_intern("utc_offset"), 0);
|
1628
1374
|
VALUE usec = rb_funcall(time, rb_intern("tv_usec"), 0);
|
1629
|
-
SqlTimestamp sqlTimestamp(NUM2LONG(sec), NUM2INT(usec) *
|
1375
|
+
SqlTimestamp sqlTimestamp(NUM2LONG(sec), NUM2INT(usec) * NANOS_PER_MICRO);// + NUM2INT(offset)
|
1630
1376
|
statement->setTimestamp(index, &sqlTimestamp);
|
1631
1377
|
break;
|
1632
1378
|
}
|
@@ -1711,7 +1457,7 @@ VALUE nuodb_prepared_statement_bind_params(VALUE self, VALUE array)
|
|
1711
1457
|
{
|
1712
1458
|
trace("nuodb_prepared_statement_bind_params");
|
1713
1459
|
|
1714
|
-
nuodb_prepared_statement_handle
|
1460
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1715
1461
|
if (handle != NULL && handle->pointer != NULL)
|
1716
1462
|
{
|
1717
1463
|
for (int i = 0; i < RARRAY_LEN(array); ++i)
|
@@ -1741,7 +1487,7 @@ VALUE nuodb_prepared_statement_execute(VALUE self)
|
|
1741
1487
|
{
|
1742
1488
|
trace("nuodb_prepared_statement_execute");
|
1743
1489
|
|
1744
|
-
nuodb_prepared_statement_handle
|
1490
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1745
1491
|
if (handle != NULL && handle->pointer != NULL)
|
1746
1492
|
{
|
1747
1493
|
try
|
@@ -1771,7 +1517,7 @@ VALUE nuodb_prepared_statement_update_count(VALUE self)
|
|
1771
1517
|
{
|
1772
1518
|
trace("nuodb_prepared_statement_update_count");
|
1773
1519
|
|
1774
|
-
nuodb_prepared_statement_handle
|
1520
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1775
1521
|
if (handle != NULL && handle->pointer != NULL)
|
1776
1522
|
{
|
1777
1523
|
try
|
@@ -1800,20 +1546,22 @@ static VALUE nuodb_prepared_statement_results(VALUE self)
|
|
1800
1546
|
{
|
1801
1547
|
trace("nuodb_prepared_statement_results");
|
1802
1548
|
|
1803
|
-
nuodb_prepared_statement_handle
|
1804
|
-
if (handle != NULL && handle->pointer != NULL)
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1549
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1550
|
+
if (handle != NULL && handle->pointer != NULL) {
|
1551
|
+
try {
|
1552
|
+
VALUE ruby_handle = nuodb_result_init(self, handle->pointer->getResultSet(), handle->pointer->getConnection());
|
1553
|
+
nuodb_result_handle* our_result_handle = cast_handle<nuodb_result_handle>(ruby_handle);
|
1554
|
+
|
1555
|
+
assert(our_result_handle != NULL);
|
1556
|
+
assert(our_result_handle->prepStmt == NULL);
|
1557
|
+
assert(our_result_handle->stmt == NULL);
|
1558
|
+
|
1559
|
+
our_result_handle->prepStmt = handle;
|
1560
|
+
return ruby_handle;
|
1561
|
+
} catch (SQLException & e) {
|
1812
1562
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to get the result set for the prepared statement: %s", e.getText());
|
1813
1563
|
}
|
1814
|
-
}
|
1815
|
-
else
|
1816
|
-
{
|
1564
|
+
} else {
|
1817
1565
|
rb_raise(rb_eArgError, "invalid state: prepared statement handle nil");
|
1818
1566
|
}
|
1819
1567
|
return Qnil;
|
@@ -1830,26 +1578,27 @@ static VALUE nuodb_prepared_statement_generated_keys(VALUE self)
|
|
1830
1578
|
{
|
1831
1579
|
trace("nuodb_prepared_statement_generated_keys");
|
1832
1580
|
|
1833
|
-
nuodb_prepared_statement_handle
|
1834
|
-
if (handle != NULL && handle->pointer != NULL)
|
1835
|
-
|
1836
|
-
try
|
1837
|
-
{
|
1581
|
+
nuodb_prepared_statement_handle* handle = cast_handle<nuodb_prepared_statement_handle>(self);
|
1582
|
+
if (handle != NULL && handle->pointer != NULL) {
|
1583
|
+
try {
|
1838
1584
|
// this hack should not have been necessary; it should never have
|
1839
1585
|
// returned null, this is a product defect.
|
1840
|
-
ResultSet
|
1841
|
-
if (results != NULL)
|
1842
|
-
|
1843
|
-
|
1586
|
+
ResultSet* results = handle->pointer->getGeneratedKeys();
|
1587
|
+
if (results != NULL) {
|
1588
|
+
VALUE ruby_handle = nuodb_result_init(self, results, handle->pointer->getConnection());
|
1589
|
+
nuodb_result_handle* our_result_handle = cast_handle<nuodb_result_handle>(ruby_handle);
|
1590
|
+
|
1591
|
+
assert(our_result_handle != NULL);
|
1592
|
+
assert(our_result_handle->prepStmt == NULL);
|
1593
|
+
assert(our_result_handle->stmt == NULL);
|
1594
|
+
|
1595
|
+
our_result_handle->prepStmt = handle;
|
1596
|
+
return ruby_handle;
|
1844
1597
|
}
|
1845
|
-
}
|
1846
|
-
catch (SQLException & e)
|
1847
|
-
{
|
1598
|
+
} catch (SQLException & e) {
|
1848
1599
|
rb_raise_nuodb_error(e.getSqlcode(), "Failed to get the generated keys for the prepared statement: %s", e.getText());
|
1849
1600
|
}
|
1850
|
-
}
|
1851
|
-
else
|
1852
|
-
{
|
1601
|
+
} else {
|
1853
1602
|
rb_raise(rb_eArgError, "invalid state: prepared statement handle nil");
|
1854
1603
|
}
|
1855
1604
|
return Qnil;
|
@@ -1888,56 +1637,38 @@ void nuodb_define_prepared_statement_api()
|
|
1888
1637
|
*/
|
1889
1638
|
|
1890
1639
|
static
|
1891
|
-
|
1640
|
+
void nuodb_connection_free(void* ptr)
|
1892
1641
|
{
|
1893
|
-
trace("
|
1642
|
+
trace("nuodb_connection_free");
|
1643
|
+
if (ptr != NULL) {
|
1644
|
+
nuodb_connection_handle* handle = (nuodb_connection_handle*)ptr;
|
1645
|
+
NuoDB::SQLException* err = handle_free(handle, NULL);
|
1894
1646
|
|
1895
|
-
|
1896
|
-
|
1897
|
-
|
1898
|
-
|
1899
|
-
|
1900
|
-
if (handle->pointer != NULL)
|
1901
|
-
{
|
1902
|
-
try
|
1903
|
-
{
|
1904
|
-
track_ref_count("CLOSE CONN", handle);
|
1905
|
-
log(INFO, "closing connection");
|
1906
|
-
handle->pointer->close();
|
1907
|
-
handle->pointer = NULL;
|
1908
|
-
}
|
1909
|
-
catch (SQLException & e)
|
1910
|
-
{
|
1911
|
-
log(DEBUG, "rb_raise");
|
1912
|
-
rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close connection: %s", e.getText());
|
1913
|
-
}
|
1647
|
+
if (err) {
|
1648
|
+
//Not ok to raise a ruby exception during GC
|
1649
|
+
//rb_raise_nuodb_error(err->getSqlcode(), "Failed to successfully close connection: %s", err->getText());
|
1650
|
+
log(ERROR, "Failed to successfully close connection");
|
1651
|
+
log(ERROR, err->getText());
|
1914
1652
|
}
|
1915
1653
|
}
|
1916
|
-
return Qnil;
|
1917
1654
|
}
|
1918
1655
|
|
1919
1656
|
static
|
1920
|
-
void
|
1657
|
+
void nuodb_connection_cleanup(nuodb_handle* handle)
|
1921
1658
|
{
|
1922
|
-
|
1923
|
-
|
1924
|
-
{
|
1925
|
-
|
1926
|
-
rb_protect(nuodb_connection_free_protect, reinterpret_cast<VALUE>(ptr), &exception);
|
1927
|
-
if (exception)
|
1928
|
-
{
|
1929
|
-
rb_jump_tag(exception);
|
1930
|
-
}
|
1659
|
+
nuodb_connection_handle* connectionHandle = (nuodb_connection_handle*)handle;
|
1660
|
+
|
1661
|
+
if (connectionHandle && connectionHandle->pointer) {
|
1662
|
+
connectionHandle->pointer->close();
|
1931
1663
|
}
|
1932
1664
|
}
|
1933
1665
|
|
1934
1666
|
static
|
1935
|
-
void nuodb_connection_mark(void
|
1667
|
+
void nuodb_connection_mark(void* ptr)
|
1936
1668
|
{
|
1937
1669
|
trace("nuodb_connection_mark");
|
1938
1670
|
|
1939
|
-
nuodb_connection_handle
|
1940
|
-
track_ref_count("MARK CONN", handle);
|
1671
|
+
nuodb_connection_handle* handle = (nuodb_connection_handle *)ptr;
|
1941
1672
|
|
1942
1673
|
rb_gc_mark(handle->database);
|
1943
1674
|
rb_gc_mark(handle->username);
|
@@ -1945,38 +1676,28 @@ void nuodb_connection_mark(void * ptr)
|
|
1945
1676
|
rb_gc_mark(handle->schema);
|
1946
1677
|
}
|
1947
1678
|
|
1948
|
-
static
|
1949
|
-
void nuodb_connection_decr_reference_count(nuodb_handle * handle)
|
1950
|
-
{
|
1951
|
-
trace("nuodb_connection_decr_reference_count");
|
1952
|
-
decr_reference_count(handle);
|
1953
|
-
}
|
1954
|
-
|
1955
1679
|
static
|
1956
1680
|
VALUE nuodb_connection_alloc(VALUE klass)
|
1957
1681
|
{
|
1958
1682
|
trace("nuodb_connection_alloc");
|
1959
1683
|
|
1960
|
-
|
1684
|
+
trace("alloc");
|
1685
|
+
nuodb_connection_handle* handle = ALLOC(struct nuodb_connection_handle);
|
1686
|
+
handle_init(handle, NULL, 4, nuodb_connection_cleanup);
|
1961
1687
|
handle->database = Qnil;
|
1962
1688
|
handle->username = Qnil;
|
1963
1689
|
handle->password = Qnil;
|
1964
1690
|
handle->schema = Qnil;
|
1965
1691
|
handle->timezone = Qnil;
|
1966
1692
|
|
1967
|
-
handle->free_func = RUBY_DATA_FUNC(&nuodb_connection_free);
|
1968
|
-
handle->atomic = 0;
|
1969
|
-
handle->parent = Qnil;
|
1970
|
-
handle->parent_handle = 0;
|
1971
1693
|
handle->pointer = 0;
|
1972
|
-
incr_reference_count(handle);
|
1973
1694
|
|
1974
1695
|
print_address("[ALLOC] connection", handle);
|
1975
1696
|
|
1976
|
-
return Data_Wrap_Struct(klass, nuodb_connection_mark,
|
1697
|
+
return Data_Wrap_Struct(klass, nuodb_connection_mark, nuodb_connection_free, handle);
|
1977
1698
|
}
|
1978
1699
|
|
1979
|
-
static void internal_connection_connect_or_raise(nuodb_connection_handle
|
1700
|
+
static void internal_connection_connect_or_raise(nuodb_connection_handle* handle)
|
1980
1701
|
{
|
1981
1702
|
trace("internal_connection_connect_or_raise");
|
1982
1703
|
|
@@ -1985,7 +1706,7 @@ static void internal_connection_connect_or_raise(nuodb_connection_handle * handl
|
|
1985
1706
|
try
|
1986
1707
|
{
|
1987
1708
|
handle->pointer = Connection::create();
|
1988
|
-
Properties
|
1709
|
+
Properties* props = handle->pointer->allocProperties();
|
1989
1710
|
props->putValue("user", StringValueCStr(handle->username));
|
1990
1711
|
props->putValue("password", StringValueCStr(handle->password));
|
1991
1712
|
props->putValue("schema", StringValueCStr(handle->schema));
|
@@ -2010,7 +1731,7 @@ static void internal_connection_connect_or_raise(nuodb_connection_handle * handl
|
|
2010
1731
|
try
|
2011
1732
|
{
|
2012
1733
|
handle->pointer = Connection::create();
|
2013
|
-
Properties
|
1734
|
+
Properties* props = handle->pointer->allocProperties();
|
2014
1735
|
props->putValue("user", StringValueCStr(handle->username));
|
2015
1736
|
props->putValue("password", StringValueCStr(handle->password));
|
2016
1737
|
if (!NIL_P(handle->timezone))
|
@@ -2045,7 +1766,7 @@ static VALUE nuodb_connection_commit(VALUE self)
|
|
2045
1766
|
{
|
2046
1767
|
trace("nuodb_connection_commit");
|
2047
1768
|
|
2048
|
-
nuodb_connection_handle
|
1769
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2049
1770
|
if (handle != NULL && handle->pointer != NULL)
|
2050
1771
|
{
|
2051
1772
|
try
|
@@ -2073,44 +1794,9 @@ static VALUE nuodb_connection_commit(VALUE self)
|
|
2073
1794
|
static VALUE nuodb_connection_disconnect(VALUE self)
|
2074
1795
|
{
|
2075
1796
|
trace("nuodb_connection_disconnect");
|
2076
|
-
nuodb_connection_handle
|
2077
|
-
track_ref_count("CONN DISCONNECT", handle);
|
1797
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);//;
|
2078
1798
|
nuodb_connection_free(handle);
|
2079
|
-
// if (handle != NULL)
|
2080
|
-
// {
|
2081
|
-
// track_ref_count("FREE CONN", handle);
|
2082
|
-
// if (handle->pointer != NULL)
|
2083
|
-
// {
|
2084
|
-
// try
|
2085
|
-
// {
|
2086
|
-
// track_ref_count("CLOSE CONN", handle);
|
2087
|
-
// handle->pointer->close();
|
2088
|
-
// handle->pointer = NULL;
|
2089
|
-
// }
|
2090
|
-
// catch (SQLException & e)
|
2091
|
-
// {
|
2092
|
-
// log(DEBUG, "rb_raise");
|
2093
|
-
// rb_raise_nuodb_error(e.getSqlcode(), "Failed to successfully close connection: %s", e.getText());
|
2094
|
-
// }
|
2095
|
-
// }
|
2096
|
-
// }
|
2097
1799
|
return Qnil;
|
2098
|
-
//
|
2099
|
-
//
|
2100
|
-
//
|
2101
|
-
// if (ENABLE_CLOSE_HOOK)
|
2102
|
-
// {
|
2103
|
-
// nuodb_connection_handle * handle = cast_handle<nuodb_connection_handle>(self);
|
2104
|
-
// if (handle != NULL && handle->pointer != NULL)
|
2105
|
-
// {
|
2106
|
-
// nuodb_connection_decr_reference_count(handle);
|
2107
|
-
// }
|
2108
|
-
// else
|
2109
|
-
// {
|
2110
|
-
// rb_raise(rb_eArgError, "invalid state: connection handle nil");
|
2111
|
-
// }
|
2112
|
-
// }
|
2113
|
-
// return Qnil;
|
2114
1800
|
}
|
2115
1801
|
|
2116
1802
|
/*
|
@@ -2126,7 +1812,7 @@ static VALUE nuodb_connection_ping(VALUE self)
|
|
2126
1812
|
{
|
2127
1813
|
trace("nuodb_connection_ping");
|
2128
1814
|
|
2129
|
-
nuodb_connection_handle
|
1815
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2130
1816
|
if (handle != NULL && handle->pointer != NULL)
|
2131
1817
|
{
|
2132
1818
|
try
|
@@ -2197,7 +1883,7 @@ static VALUE nuodb_connection_rollback(VALUE self)
|
|
2197
1883
|
{
|
2198
1884
|
trace("nuodb_connection_rollback");
|
2199
1885
|
|
2200
|
-
nuodb_connection_handle
|
1886
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2201
1887
|
if (handle != NULL && handle->pointer != NULL)
|
2202
1888
|
{
|
2203
1889
|
try
|
@@ -2234,7 +1920,7 @@ static VALUE nuodb_connection_autocommit_set(VALUE self, VALUE value)
|
|
2234
1920
|
{
|
2235
1921
|
trace("nuodb_connection_autocommit_set");
|
2236
1922
|
|
2237
|
-
nuodb_connection_handle
|
1923
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2238
1924
|
if (handle != NULL && handle->pointer != NULL)
|
2239
1925
|
{
|
2240
1926
|
bool auto_commit = !(RB_TYPE_P(value, T_FALSE) || RB_TYPE_P(value, T_NIL));
|
@@ -2270,7 +1956,7 @@ static VALUE nuodb_connection_autocommit_get(VALUE self)
|
|
2270
1956
|
{
|
2271
1957
|
trace("nuodb_connection_autocommit_get");
|
2272
1958
|
|
2273
|
-
nuodb_connection_handle
|
1959
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2274
1960
|
if (handle != NULL && handle->pointer != NULL)
|
2275
1961
|
{
|
2276
1962
|
try
|
@@ -2322,7 +2008,7 @@ static VALUE nuodb_connection_initialize(VALUE self, VALUE hash)
|
|
2322
2008
|
rb_raise(rb_eTypeError, "wrong argument type %s (Hash expected)", rb_class2name(CLASS_OF(hash)));
|
2323
2009
|
}
|
2324
2010
|
|
2325
|
-
nuodb_connection_handle
|
2011
|
+
nuodb_connection_handle* handle = cast_handle<nuodb_connection_handle>(self);
|
2326
2012
|
if (NIL_P(handle->database))
|
2327
2013
|
{
|
2328
2014
|
VALUE value = rb_hash_aref(hash, sym_database);
|
@@ -2417,42 +2103,6 @@ static VALUE nuodb_connection_initialize(VALUE self, VALUE hash)
|
|
2417
2103
|
return Qnil;
|
2418
2104
|
}
|
2419
2105
|
|
2420
|
-
///*
|
2421
|
-
// * call-seq:
|
2422
|
-
// * tables(schema = nil) -> Results
|
2423
|
-
// *
|
2424
|
-
// * Retrieves a result set containing the tables associated to the specified schema,
|
2425
|
-
// * or if the specified schema is nil, return a result set of tables for the schema
|
2426
|
-
// * associated with the connection.
|
2427
|
-
// */
|
2428
|
-
//static VALUE nuodb_connection_tables(VALUE self, VALUE schema)
|
2429
|
-
//{
|
2430
|
-
// trace("nuodb_connection_tables");
|
2431
|
-
//
|
2432
|
-
// nuodb_connection_handle * handle = cast_handle<nuodb_connection_handle>(self);
|
2433
|
-
// if (handle != NULL && handle->pointer != NULL)
|
2434
|
-
// {
|
2435
|
-
// if (schema == Qnil)
|
2436
|
-
// {
|
2437
|
-
// schema = handle->schema;
|
2438
|
-
// }
|
2439
|
-
//// char const * sql = "SELECT tablename FROM system.tables WHERE schema = ?"
|
2440
|
-
//// try
|
2441
|
-
//// {
|
2442
|
-
//// return nuodb_result_alloc(self, handle->pointer->getGeneratedKeys());
|
2443
|
-
//// }
|
2444
|
-
//// catch (SQLException & e)
|
2445
|
-
//// {
|
2446
|
-
//// rb_raise_nuodb_error(e.getSqlcode(), "Failed to get the tables keys for the schema: %s", e.getText());
|
2447
|
-
//// }
|
2448
|
-
// }
|
2449
|
-
// else
|
2450
|
-
// {
|
2451
|
-
// rb_raise(rb_eArgError, "invalid state: connection handle nil");
|
2452
|
-
// }
|
2453
|
-
// return Qnil;
|
2454
|
-
//}
|
2455
|
-
|
2456
2106
|
void nuodb_define_connection_api()
|
2457
2107
|
{
|
2458
2108
|
/*
|