rq-ruby1.8 3.4.3 → 3.4.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,22 +1,14 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
2
 
6
3
  # Runtime dependencies
7
- # gem "bio", ">= 1.3.1"
8
- # gem "bio-logger", "> 0.8.0"
9
- # gem "nokogiri", ">= 1.4.4"
10
4
  gem "posixlock"
11
5
  gem "arrayfields"
12
6
  gem "lockfile"
13
- # gem "sqlite-1.3.1" # on rubygems?
7
+ # gem "sqlite-1.3.1" # now included with rq-ruby1.8
14
8
 
15
9
  # Add dependencies to develop your gem here.
16
10
  # Include everything needed to run rake, tests, features, etc.
17
11
  group :development do
18
- # gem "rspec", "~> 2.3.0"
19
12
  gem "bundler", "~> 1.0.15"
20
13
  gem "jeweler", "~> 1.6.4"
21
- # gem "rcov", ">= 0"
22
14
  end
data/INSTALL CHANGED
@@ -4,85 +4,66 @@ The current version of rq runs on ruby1.8. A gem is available on rubygems:
4
4
 
5
5
  https://rubygems.org/gems/rq-ruby1.8
6
6
 
7
- install with
7
+ simply with
8
+
9
+ install sqlite2 (Debian apt-get install libsqlite0-dev)
10
+
11
+ and
8
12
 
9
13
  gem1.8 install rq-ruby1.8
10
14
 
11
- which should include:
15
+ The gem includes sqlite-1.3.1 for Ruby. And should include:
12
16
 
13
17
  - gem1.8 install posixlock
14
18
  - gem1.8 install arrayfields
15
19
  - gem1.8 install lockfile
16
20
 
17
- sqlite-1.3.1, however, is not on rubygems, so you may need to:
18
-
19
- - install sqlite2 (Debian apt-get install libsqlite0-dev)
20
- - wget http://rubyforge.org/frs/download.php/1070/sqlite-1.3.1.gem
21
- - gem1.8 install sqlite-1.3.1.gem
22
- - gem1.8 install rq-ruby1.8 (or run from source)
21
+ gems also available from http://bio4.dnsalias.net/download/gem/ruby1.8/
23
22
 
24
- Also available from http://bio4.dnsalias.net/download/gem/ruby1.8/
23
+ Find rq
25
24
 
26
- run with, for example
25
+ gem1.8 contents rq-ruby1.8|grep bin/rq$
26
+
27
+ Maybe link it
27
28
 
28
- ln -s /var/lib/gems/1.8/gems/rq-ruby1.8-3.4.3/bin/rq /usr/local/bin/rq
29
+ ln -sf `gem1.8 contents rq-ruby1.8|grep bin/rq$` /usr/local/bin/rq
29
30
  rq --help
30
31
 
31
32
  === Debian
32
33
 
33
34
  On Debian systems, the recommended procedure is to use Debian apt on all
34
- machines. For now, use the 3.4.3 install, as documented in the README!
35
+ machines. For now, use the gem install, as documented in the README!
35
36
 
36
37
  This has been tested on Debian Squeeze (BioLinux Minimal):
37
38
 
38
- root@vagrant-debian-squeeze:/home/vagrant# gem1.8 install rq-ruby1.8
39
- Building native extensions. This could take a while...
40
- Successfully installed posixlock-0.0.1
41
- Successfully installed arrayfields-4.7.4
42
- Successfully installed lockfile-1.4.3
43
- Successfully installed rq-ruby1.8-3.4.3
44
- 4 gems installed
45
- Installing ri documentation for posixlock-0.0.1...
46
- Installing ri documentation for arrayfields-4.7.4...
47
- Installing ri documentation for lockfile-1.4.3...
48
- Installing ri documentation for rq-ruby1.8-3.4.3...
49
- Installing RDoc documentation for posixlock-0.0.1...
50
- Installing RDoc documentation for arrayfields-4.7.4...
51
- Installing RDoc documentation for lockfile-1.4.3...
52
- Installing RDoc documentation for rq-ruby1.8-3.4.3...
53
-
54
- ln -s /var/lib/gems/1.8/gems/rq-ruby1.8-3.4.3/bin/rq /usr/local/bin/rq
55
-
56
- apt-get install libsqlite0-dev
57
- Setting up libsqlite0 (2.8.17-6) ...
58
- Setting up libsqlite0-dev (2.8.17-6) ...
59
- wget http://rubyforge.org/frs/download.php/1070/sqlite-1.3.1.gem
60
- Saving to: `sqlite-1.3.1.gem'
61
- 100%[======================================>] 41,278 --.-K/s in 0.1s
62
- 2011-07-21 11:36:21 (347 KB/s) - `sqlite-1.3.1.gem' saved [41278/41278]
63
-
64
- root@vagrant-debian-squeeze:/home/vagrant# gem1.8 install sqlite-1.3.1.gem
65
- Building native extensions. This could take a while...
66
- Successfully installed sqlite-1.3.1
67
- 1 gem installed
68
- Installing ri documentation for sqlite-1.3.1...
69
- Installing RDoc documentation for sqlite-1.3.1...
39
+ apt-get install libsqlite0-dev
40
+ Setting up libsqlite0 (2.8.17-6) ...
41
+ Setting up libsqlite0-dev (2.8.17-6) ...
42
+
43
+ gem1.8 install rq-ruby1.8
44
+ Building native extensions. This could take a while...
45
+ Successfully installed posixlock-0.0.1
46
+ Successfully installed arrayfields-4.7.4
47
+ Successfully installed lockfile-1.4.3
48
+ Successfully installed rq-ruby1.8-3.4.4
49
+ 4 gems installed
50
+ Installing ri documentation for posixlock-0.0.1...
51
+ Installing ri documentation for arrayfields-4.7.4...
52
+ Installing ri documentation for lockfile-1.4.3...
53
+ Installing ri documentation for rq-ruby1.8-3.4.4...
54
+ Installing RDoc documentation for posixlock-0.0.1...
55
+ Installing RDoc documentation for arrayfields-4.7.4...
56
+ Installing RDoc documentation for lockfile-1.4.3...
57
+ Installing RDoc documentation for rq-ruby1.8-3.4.4...
58
+
59
+ ln -sf `gem1.8 contents rq-ruby1.8|grep bin/rq$` /usr/local/bin/rq
60
+
70
61
  root@vagrant-debian-squeeze:/home/vagrant# rq --help
71
62
  NAME
72
63
 
73
- rq v3.4.3
64
+ rq v3.4.4
74
65
 
75
- (the end!)
76
-
77
- (below will become available later)
78
-
79
- * apt-get install rq-ruby1.8
80
-
81
- which resolves all dependencies, or alternatively
82
-
83
- * Download the rq deb file from http://bio4.dnsalias.net/download/Debian/
84
- * apt-get install libposixlock-ruby1.8 libsqlite3-ruby1.8 ruby1.8
85
- * dpkg --force-architecture -i rq-ruby1.8-ver.deb
66
+ (...)
86
67
 
87
68
  which works on on 32-bits and 64-bits systems. The commands
88
69
 
@@ -135,12 +116,6 @@ version >4.4
135
116
  install which all cluster nodes can use. The other install methods mean
136
117
  you will have to install rq on __each__ node you plan to use it on.
137
118
 
138
- === RUBYGEMS
139
-
140
- (currently defunct, awaits updating rq to Ruby 1.9.x and sqlite3)
141
-
142
- * gem install rq
143
-
144
119
  === STANDARD
145
120
 
146
121
  (in rq version <=3.4.0)
@@ -164,3 +139,23 @@ The current version of rq runs on ruby1.8, using bundler and jeweler:
164
139
  rake gemspec
165
140
  rake build # creates gem in ./pkg
166
141
 
142
+ == Trouble shooting
143
+
144
+ === rubyio.h error
145
+
146
+ Building native extensions. This could take a while...
147
+ ERROR: Error installing rq-ruby1.8-3.4.5.gem:
148
+ ERROR: Failed to build gem native extension.
149
+
150
+ /usr/local/include/ruby-1.9.1/ruby/backward/rubyio.h:2:2: warning: #warning use "ruby/io.h" instead of "rubyio.h"
151
+
152
+ Solution: you are trying to build against ruby1.9. Use gem1.8 instead. If you
153
+ have problems mixing gems, take a look at 'rvm'.
154
+
155
+ === can not find rq, after successful install
156
+
157
+ gem1.8 stores gems in dirs named /var/lib/gems/1.8/gems/rq-ruby1.8-3.4.5/. You
158
+ may have to create a symbolic link, e.g.
159
+
160
+ ln -sf `gem1.8 contents rq-ruby1.8|grep bin/rq$` /usr/local/bin/rq
161
+
data/README CHANGED
@@ -1,41 +1,108 @@
1
1
  NAME
2
2
 
3
- rq v3.4.3
3
+ rq v3.4.5
4
4
 
5
5
  SYNOPSIS
6
6
 
7
- rq (queue | export RQ_Q=q) mode [mode_args]* [options]*
7
+ rq queue mode [mode_args]* [options]*
8
8
 
9
+ ruby queue (rq) is a zero-admin zero-configuration tool used to create
10
+ instant unix clusters on a multi-core machine, and/or multiple nodes in a
11
+ network, or in the Cloud. rq requires only a centrally mounted directory
12
+ (e.g. NFS) in order to manage a simple sqlite database as a distributed
13
+ priority work queue. See QUICK START below.
9
14
 
10
- URIS
11
15
 
12
- https://github.com/pjotrp/rq - main website
13
- http://www.linuxjournal.com/article/7922
16
+ DESCRIPTION
14
17
 
15
- and
16
-
17
- http://rubyforge.org/projects/codeforpeople/
18
- http://codeforpeople.com/lib/ruby/rq/
18
+ ruby queue (rq) is a zero-admin zero-configuration tool used to create
19
+ instant unix clusters. the simple design allows researchers with minimal unix
20
+ experience to install and configure, in only a few minutes and without root
21
+ privileges, a robust unix cluster capable of distributing processes to many
22
+ nodes - bringing dozens of powerful cpus to their knees with a single blow.
23
+ clearly this software should be kept out of the hands of free radicals, seti
24
+ enthusiasts, and one mr. j safran.
19
25
 
20
- LICENSE
26
+ the central concept of rq is that n nodes work in isolation to pull jobs
27
+ from an centrally mounted nfs priority work queue in a synchronized fashion.
28
+ the nodes have absolutely no knowledge of each other and all communication
29
+ is done via the queue meaning that, so long as the queue is available via
30
+ nfs and a single node is running jobs from it, the system will continue to
31
+ process jobs. there is no centralized process whatsoever - all nodes work
32
+ to take jobs from the queue and run them as fast as possible. this creates
33
+ a system which load balances automatically and is robust in face of node
34
+ failures.
21
35
 
22
- rq is distributed under the BSD license, see the ./LICENSE file
36
+ although the rq system is simple in it's design it features powerful
37
+ functionality such as priority management, predicate and sql query, compact
38
+ streaming command-line processing, programmable api, hot-backup, and
39
+ input/capture of the stdin/stdout/stderr io streams of remote jobs. to date
40
+ rq has had no reported runtime failures and is in operation at
41
+ dozens of research centers around the world. while rq is written in
42
+ the Ruby programming language, there is no Ruby programming
43
+ involved in using rq.
44
+
45
+ QUICK START
46
+
47
+ install rq using rubygems
48
+
49
+ gem1.8 install rq-ruby1.8
50
+ ln -sf `gem1.8 contents rq-ruby1.8|grep bin/rq$` /usr/local/bin/rq
51
+ rq --help
52
+
53
+ set up a directory for the queue - this can be a local, or an NFS/sshfs
54
+ mounted drive:
55
+
56
+ rq dir create
57
+
58
+ on every node create a queue runner, specifying the number of cores (here 8)
59
+
60
+ rq dir feed --daemon --log=rq.log --max_feed=8
61
+
62
+ submit two jobs - shell style
63
+
64
+ rq dir submit 'sleep 10'
65
+ rq dir submit 'sleep 9'
66
+
67
+ check status
68
+
69
+ rq dir status
70
+
71
+ shows
72
+
73
+ ---
74
+ jobs:
75
+ pending: 0
76
+ holding: 0
77
+ running: 2
78
+ finished: 0
79
+ dead: 0
80
+ total: 2
81
+ temporal:
82
+ running:
83
+ min: {2: 00h00m03.49s}
84
+ max: {1: 00h00m03.60s}
85
+ performance:
86
+ avg_time_per_job: 00h00m00.00s
87
+ n_jobs_in_last_hrs:
88
+ 1: 0
89
+ 12: 0
90
+ 24: 0
91
+ exit_status:
92
+ successes: 0
93
+ failures: 0
94
+ ok: 0
95
+
96
+ Now, that was easy!!
23
97
 
24
98
  INSTALL
25
99
 
26
100
  See the ./INSTALL file, but quickly
27
101
 
28
- gems (per node):
29
-
30
- gem >=3.4.3:
102
+ gem >=3.4.5:
31
103
 
32
- - install sqlite2 (Debian apt-get install libsqlite0-dev)
33
- - wget http://rubyforge.org/frs/download.php/1070/sqlite-1.3.1.gem
34
- - gem1.8 install sqlite-1.3.1.gem
35
- - gem1.8 install posixlock
36
- - gem1.8 install arrayfields
37
- - gem1.8 install lockfile
38
- - gem1.8 install rq-ruby1.8 (or run from source)
104
+ - install sqlite2 (Debian apt-get install libsqlite0-dev)
105
+ - gem1.8 install rq-ruby1.8
39
106
 
40
107
  Also available from http://bio4.dnsalias.net/download/gem/ruby1.8/
41
108
 
@@ -52,37 +119,6 @@ INSTALL
52
119
 
53
120
  see ./INSTALL file for latest
54
121
 
55
- DESCRIPTION
56
-
57
- ruby queue (rq) is a zero-admin zero-configuration tool used to create instant
58
- unix clusters. rq requires only a central nfs filesystem in order to manage a
59
- simple sqlite database as a distributed priority work queue. this simple
60
- design allows researchers with minimal unix experience to install and
61
- configure, in only a few minutes and without root privileges, a robust unix
62
- cluster capable of distributing processes to many nodes - bringing dozens of
63
- powerful cpus to their knees with a single blow. clearly this software should
64
- be kept out of the hands of free radicals, seti enthusiasts, and one mr. j
65
- safran.
66
-
67
- the central concept of rq is that n nodes work in isolation to pull jobs
68
- from an centrally mounted nfs priority work queue in a synchronized fashion.
69
- the nodes have absolutely no knowledge of each other and all communication
70
- is done via the queue meaning that, so long as the queue is available via
71
- nfs and a single node is running jobs from it, the system will continue to
72
- process jobs. there is no centralized process whatsoever - all nodes work
73
- to take jobs from the queue and run them as fast as possible. this creates
74
- a system which load balances automatically and is robust in face of node
75
- failures.
76
-
77
- although the rq system is simple in it's design it features powerful
78
- functionality such as priority management, predicate and sql query, compact
79
- streaming command-line processing, programmable api, hot-backup, and
80
- input/capture of the stdin/stdout/stderr io streams of remote jobs. to date
81
- rq has had no reported runtime failures and is in operation at
82
- dozens of research centers around the world. while rq is written in
83
- the Ruby programming language, there is no Ruby programming
84
- involved in using rq.
85
-
86
122
  INVOCATION
87
123
 
88
124
  the first argument to any rq command is the always the name of the queue
@@ -1086,6 +1122,16 @@ DIAGNOSTICS
1086
1122
  success : $? == 0
1087
1123
  failure : $? != 0
1088
1124
 
1125
+ URIS
1126
+
1127
+ https://github.com/pjotrp/rq - main website
1128
+ http://www.linuxjournal.com/article/7922
1129
+ http://rubyforge.org/projects/codeforpeople/ (original)
1130
+
1131
+ LICENSE
1132
+
1133
+ rq is distributed under the BSD license, see the ./LICENSE file
1134
+
1089
1135
  CREDITS
1090
1136
 
1091
1137
  - kim baugh : patient tester and design input
@@ -1098,7 +1144,7 @@ CREDITS
1098
1144
 
1099
1145
  INSTALL
1100
1146
 
1101
- gem install rq-ruby1.8 (see top of page)
1147
+ gem1.8 install rq-ruby1.8 (see top of page)
1102
1148
 
1103
1149
  TEST
1104
1150
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.4.3
1
+ 3.4.5
data/bin/rq CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby1.8
2
2
 
3
- $: << '/var/lib/gems/1.8/gems/rq-ruby1.8-3.4.3/lib' # locate gem1.8 install
3
+ $: << '/var/lib/gems/1.8/gems/rq-ruby1.8-3.4.5/lib' # locate gem1.8 install
4
4
  $: << '/usr/share/rq-ruby1.8/lib'
5
5
 
6
6
  #
@@ -0,0 +1,7 @@
1
+ require 'mkmf'
2
+
3
+ dir_config( "sqlite" )
4
+ have_library( "sqlite" )
5
+ if have_header( "sqlite.h" ) and have_library( "sqlite", "sqlite_open" )
6
+ create_makefile( "_sqlite" )
7
+ end
@@ -0,0 +1,862 @@
1
+ /* --------------------------------------------------------------------------
2
+ * sqlite.c -- glue code between for the SQLite database and Ruby.
3
+ * Copyright (C) 2003 Jamis Buck (jgb3@email.byu.edu)
4
+ * --------------------------------------------------------------------------
5
+ * The SQLite/Ruby module is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU General Public License as published
7
+ * by the Free Software Foundation; either version 2 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * The SQLite/Ruby Interface is free software; you can redistribute it and/or
11
+ * modify it under the terms of the BSD License as published by the Free
12
+ * Software Foundation. See also the rq LICENSE file.
13
+ *
14
+ * The license was changed for older sqlite-1.3.1 in agreement with Jamis Buck.
15
+ *
16
+ * The SQLite/Ruby Interface is distributed in the hope that it will be useful,
17
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+ * --------------------------------------------------------------------------
20
+ * This file defines the glue code between the SQLite database engine and
21
+ * the Ruby interpreter.
22
+ *
23
+ * Author: Jamis Buck (jgb3@email.byu.edu)
24
+ * Date: June 2003
25
+ * --------------------------------------------------------------------------
26
+ * NOTE: rq still users the older sqlite2 engine and bindings. This will
27
+ * change.
28
+ */
29
+
30
+ #include <sqlite.h>
31
+
32
+ #include <stdio.h>
33
+ #include "ruby.h"
34
+ #include "stdarg.h"
35
+
36
+ /* these constants defines the current version of the SQLite/Ruby module */
37
+
38
+ #define LIB_VERSION_MAJOR 1
39
+ #define LIB_VERSION_MINOR 3
40
+ #define LIB_VERSION_TINY 1
41
+
42
+ /* this wraps the sqlite db pointer. We need to do it this way so that we
43
+ * can keep the object alive even after we've closed the DB handle, and we
44
+ * need to be able to tell the difference between an open and a closed DB
45
+ * handle. This way, if the 'db' member is NULL, we know the database is
46
+ * not open. */
47
+
48
+ typedef struct
49
+ {
50
+ sqlite *db;
51
+ int use_array;
52
+ } SQLITE_RUBY_DATA;
53
+
54
+
55
+ /* This represents the information for a callback during query execution. */
56
+
57
+ typedef struct
58
+ {
59
+ VALUE callback; /* the Method object to invoke for each row */
60
+ VALUE arg; /* the application-defined cookie value to pass to the method */
61
+ VALUE columns; /* a ruby array of all of the column names */
62
+ VALUE types; /* a ruby hash of all of the column types (may be null) */
63
+ int built_columns; /* whether or not the 'columns' member is valid yet */
64
+ int do_translate; /* whether or not to do type translation */
65
+ SQLITE_RUBY_DATA *self; /* a reference to the database instance being queried */
66
+ } SQLITE_RUBY_CALLBACK;
67
+
68
+ /* This represents the information for a callback on a custom SQL function */
69
+
70
+ typedef struct
71
+ {
72
+ VALUE callback; /* the Method object to invoke for each function invocation */
73
+ VALUE finalize; /* the Method object to invoke when an aggregate function is finished */
74
+ VALUE arg; /* the app-defined cookie value */
75
+ } SQLITE_CUSTOM_FUNCTION_CB;
76
+
77
+
78
+ /* global variables for defining the classes, modules, and symbols that are used by this
79
+ * module. */
80
+
81
+ static VALUE mSQLite;
82
+ static VALUE cSQLite;
83
+ static VALUE cSQLiteTypeTranslator;
84
+ static VALUE cSQLiteException;
85
+ static VALUE cSQLiteQueryContext;
86
+ static VALUE oSQLiteQueryAbort;
87
+ static ID idCallMethod;
88
+ static ID idInstanceEvalMethod;
89
+ static ID idTranslate;
90
+ static ID idFields;
91
+ static ID idFieldsEqual;
92
+
93
+ static struct {
94
+ char *name;
95
+ VALUE object;
96
+ } g_sqlite_exceptions[] = {
97
+ { "OK", 0 },
98
+ { "SQL", 0 },
99
+ { "Internal", 0 },
100
+ { "Permissions", 0 },
101
+ { "Abort", 0 },
102
+ { "Busy", 0 },
103
+ { "Locked", 0 },
104
+ { "OutOfMemory", 0 },
105
+ { "ReadOnly", 0 },
106
+ { "Interrupt", 0 },
107
+ { "IOError", 0 },
108
+ { "Corrupt", 0 },
109
+ { "NotFound", 0 },
110
+ { "Full", 0 },
111
+ { "CantOpen", 0 },
112
+ { "Protocol", 0 },
113
+ { "Empty", 0 },
114
+ { "SchemaChanged", 0 },
115
+ { "TooBig", 0 },
116
+ { "Constraint", 0 },
117
+ { "Mismatch", 0 },
118
+ { "Misuse", 0 },
119
+ { "UnsupportedOSFeature", 0 },
120
+ { "Authorization", 0 },
121
+ { NULL, 0 }
122
+ };
123
+
124
+
125
+ /* free's the given database handle when the Ruby engine garbage collects it. */
126
+ static void static_free_database_handle( SQLITE_RUBY_DATA *hdb );
127
+
128
+ /* called when a query is processing another row */
129
+ static int static_ruby_sqlite_callback( void *pArg, int argc, char **argv, char **columns );
130
+
131
+ /* called when a custom SQL function is invoked */
132
+ static void static_custom_function_callback( sqlite_func* ctx, int argc, const char **argv );
133
+
134
+ /* called when a custom aggregate SQL function is invoked */
135
+ static void static_custom_aggregate_callback( sqlite_func* ctx, int argc, const char **argv );
136
+
137
+ /* called when the custom aggregate SQL finalize function is invoked */
138
+ static void static_custom_finalize_callback( sqlite_func* ctx );
139
+
140
+ /* determines whether the given pragma is enabled or not */
141
+ static int static_pragma_enabled( sqlite* db, const char *pragma );
142
+
143
+ /* configure the various exception subclasses used by the module */
144
+ static void static_configure_exception_classes();
145
+
146
+ /* raise an exception */
147
+ static void static_raise_db_error( int code, char *msg, ... );
148
+
149
+
150
+ static VALUE static_database_new( VALUE klass,
151
+ VALUE dbname,
152
+ VALUE mode );
153
+
154
+ static VALUE static_database_close( VALUE self );
155
+
156
+ static VALUE static_database_exec( VALUE self,
157
+ VALUE sql,
158
+ VALUE callback,
159
+ VALUE parm );
160
+
161
+ static VALUE static_last_insert_rowid( VALUE self );
162
+
163
+ static VALUE static_changes( VALUE self );
164
+
165
+ static VALUE static_interrupt( VALUE self );
166
+
167
+ static VALUE static_complete( VALUE self,
168
+ VALUE sql );
169
+
170
+ static VALUE static_create_function( VALUE self,
171
+ VALUE name,
172
+ VALUE argc,
173
+ VALUE callback,
174
+ VALUE parm );
175
+
176
+ static VALUE static_create_aggregate( VALUE self,
177
+ VALUE name,
178
+ VALUE argc,
179
+ VALUE step,
180
+ VALUE finalize,
181
+ VALUE parm );
182
+
183
+ static VALUE static_aggregate_count( VALUE self );
184
+
185
+ static VALUE static_get_properties( VALUE self );
186
+
187
+ static VALUE static_is_doing_type_translation( VALUE self );
188
+
189
+ static VALUE static_set_type_translation( VALUE self, VALUE value );
190
+
191
+
192
+ static void static_free_database_handle( SQLITE_RUBY_DATA *hdb )
193
+ {
194
+ if( hdb )
195
+ {
196
+ if( hdb->db )
197
+ {
198
+ sqlite_close( hdb->db );
199
+ hdb->db = NULL;
200
+ }
201
+
202
+ free( hdb );
203
+ }
204
+ }
205
+
206
+
207
+ static int static_ruby_sqlite_callback( void *pArg, int argc, char **argv, char **columns )
208
+ {
209
+ SQLITE_RUBY_CALLBACK *hook = (SQLITE_RUBY_CALLBACK*)pArg;
210
+ VALUE result;
211
+ int i;
212
+ VALUE rc;
213
+
214
+ if( hook->self->use_array )
215
+ {
216
+ result = rb_ary_new();
217
+ }
218
+ else
219
+ {
220
+ result = rb_hash_new();
221
+ }
222
+
223
+ if( !hook->built_columns )
224
+ {
225
+ hook->columns = rb_ary_new2( argc );
226
+ }
227
+
228
+ for( i = 0; i < argc; i++ )
229
+ {
230
+ VALUE val;
231
+
232
+ if( !hook->built_columns )
233
+ {
234
+ rb_ary_push( hook->columns, rb_str_new2( columns[i] ) );
235
+ if( hook->types != Qnil )
236
+ {
237
+ VALUE type;
238
+ char *type_name = columns[ i + argc ];
239
+
240
+ type = rb_str_new2( type_name == NULL ? "STRING" : type_name );
241
+ rb_hash_aset( hook->types, rb_ary_entry( hook->columns, i ), type );
242
+ rb_hash_aset( hook->types, INT2FIX(i), type );
243
+ }
244
+ }
245
+
246
+ if( argv != NULL )
247
+ {
248
+ val = ( argv[i] ? rb_str_new2( argv[i] ) : Qnil );
249
+
250
+ if( hook->do_translate )
251
+ {
252
+ VALUE type = rb_hash_aref( hook->types, INT2FIX(i) );
253
+ val = rb_funcall( cSQLiteTypeTranslator, idTranslate, 2, type, val );
254
+ }
255
+
256
+ if( hook->self->use_array )
257
+ {
258
+ rb_ary_store( result, i, val );
259
+ }
260
+ else
261
+ {
262
+ rb_hash_aset( result, rb_ary_entry( hook->columns, i ), val );
263
+ rb_hash_aset( result, INT2FIX(i), val );
264
+ }
265
+ }
266
+ }
267
+
268
+ if( hook->self->use_array )
269
+ {
270
+ if( rb_respond_to( result, idFieldsEqual ) )
271
+ {
272
+ rb_funcall( result, idFieldsEqual, 1, hook->columns );
273
+ }
274
+ else
275
+ {
276
+ rb_iv_set( result, "@fields", hook->columns );
277
+ if( !rb_respond_to( result, idFields ) )
278
+ rb_funcall( result, idInstanceEvalMethod, 1, rb_str_new2( "def fields;@fields;end" ) );
279
+ }
280
+ }
281
+
282
+ hook->built_columns = 1;
283
+
284
+ rb_iv_set( result, "@argument", hook->arg );
285
+ rb_funcall( result, idInstanceEvalMethod, 1, rb_str_new2( "def argument;@argument;end" ) );
286
+
287
+ if( hook->types != Qnil )
288
+ {
289
+ rb_iv_set( result, "@column_types", hook->types );
290
+ rb_funcall( result, idInstanceEvalMethod, 1, rb_str_new2( "def column_types;@column_types;end" ) );
291
+ }
292
+
293
+ rc = rb_funcall( hook->callback, idCallMethod, 1, result );
294
+
295
+ return ( rc == oSQLiteQueryAbort ? 1 : 0 );
296
+ }
297
+
298
+
299
+ static void static_custom_function_callback( sqlite_func* ctx, int argc, const char **argv )
300
+ {
301
+ SQLITE_CUSTOM_FUNCTION_CB *data;
302
+ VALUE rc;
303
+ VALUE args;
304
+ int i;
305
+
306
+ data = (SQLITE_CUSTOM_FUNCTION_CB*)sqlite_user_data( ctx );
307
+
308
+ args = rb_ary_new2( argc );
309
+ rb_ary_push( args, Data_Wrap_Struct( cSQLiteQueryContext, 0, 0, ctx ) );
310
+
311
+ for( i = 0; i < argc; i++ )
312
+ {
313
+ if( argv[i] )
314
+ rb_ary_push( args, rb_str_new2( argv[i] ) );
315
+ else
316
+ rb_ary_push( args, Qnil );
317
+ }
318
+
319
+ rc = rb_apply( data->callback, idCallMethod, args );
320
+
321
+ switch( TYPE(rc) )
322
+ {
323
+ case T_STRING:
324
+ sqlite_set_result_string( ctx, STR2CSTR(rc), RSTRING(rc)->len );
325
+ break;
326
+ case T_FIXNUM:
327
+ sqlite_set_result_int( ctx, FIX2INT(rc) );
328
+ break;
329
+ case T_FLOAT:
330
+ sqlite_set_result_double( ctx, NUM2DBL(rc) );
331
+ break;
332
+ }
333
+ }
334
+
335
+
336
+ static void static_custom_aggregate_callback( sqlite_func* ctx, int argc, const char **argv )
337
+ {
338
+ SQLITE_CUSTOM_FUNCTION_CB *data;
339
+ VALUE args;
340
+ VALUE *hash;
341
+ int i;
342
+
343
+ hash = (VALUE*)sqlite_aggregate_context( ctx, sizeof( VALUE ) );
344
+ if( *hash == 0 ) *hash = rb_hash_new();
345
+
346
+ data = (SQLITE_CUSTOM_FUNCTION_CB*)sqlite_user_data( ctx );
347
+
348
+ args = rb_ary_new2( argc );
349
+ rb_ary_push( args, Data_Wrap_Struct( cSQLiteQueryContext, 0, 0, ctx ) );
350
+
351
+ for( i = 0; i < argc; i++ )
352
+ {
353
+ if( argv[i] )
354
+ rb_ary_push( args, rb_str_new2( argv[i] ) );
355
+ else
356
+ rb_ary_push( args, Qnil );
357
+ }
358
+
359
+ rb_apply( data->callback, idCallMethod, args );
360
+ }
361
+
362
+
363
+ static void static_custom_finalize_callback( sqlite_func* ctx )
364
+ {
365
+ SQLITE_CUSTOM_FUNCTION_CB *data;
366
+ VALUE rc;
367
+ int i;
368
+
369
+ data = (SQLITE_CUSTOM_FUNCTION_CB*)sqlite_user_data( ctx );
370
+ rc = rb_funcall( data->finalize, idCallMethod, 1, Data_Wrap_Struct( cSQLiteQueryContext, 0, 0, ctx ) );
371
+
372
+ switch( TYPE(rc) )
373
+ {
374
+ case T_STRING:
375
+ sqlite_set_result_string( ctx, STR2CSTR(rc), RSTRING(rc)->len );
376
+ break;
377
+ case T_FIXNUM:
378
+ sqlite_set_result_int( ctx, FIX2INT(rc) );
379
+ break;
380
+ case T_FLOAT:
381
+ sqlite_set_result_double( ctx, NUM2DBL(rc) );
382
+ break;
383
+ }
384
+ }
385
+
386
+ static int static_pragma_enabled_callback( void *arg, int argc, char **argv, char **columnNames )
387
+ {
388
+ int *result = (int*)arg;
389
+
390
+ if( ( strcmp( argv[0], "ON" ) == 0 ) || ( strcmp( argv[0], "1" ) == 0 ) )
391
+ {
392
+ *result = 1;
393
+ }
394
+ else
395
+ {
396
+ *result = 0;
397
+ }
398
+
399
+ return SQLITE_OK;
400
+ }
401
+
402
+ static int static_pragma_enabled( sqlite* db, const char *pragma )
403
+ {
404
+ int result;
405
+ int return_code;
406
+ char sql[ 256 ];
407
+ char *msg;
408
+
409
+ sprintf( sql, "PRAGMA %s", pragma );
410
+ return_code = sqlite_exec( db, sql, static_pragma_enabled_callback, &result, &msg );
411
+
412
+ if( return_code != SQLITE_OK )
413
+ {
414
+ VALUE err = rb_str_new2( msg );
415
+ free( msg );
416
+
417
+ static_raise_db_error( return_code,
418
+ "could not determine status of pragma '%s' (%s)",
419
+ pragma, STR2CSTR(err) );
420
+ }
421
+
422
+ return result;
423
+ }
424
+
425
+
426
+ /**
427
+ * Opens a SQLite database. If the database does not exist, it will be
428
+ * created. The mode parameter is currently unused and should be set to 0.
429
+ */
430
+ static VALUE static_database_new( VALUE klass,
431
+ VALUE dbname,
432
+ VALUE mode )
433
+ {
434
+ SQLITE_RUBY_DATA *hdb;
435
+ sqlite *db;
436
+ char *s_dbname;
437
+ int i_mode;
438
+ char *errmsg;
439
+ VALUE v_db;
440
+
441
+ Check_Type( dbname, T_STRING );
442
+ Check_Type( mode, T_FIXNUM );
443
+
444
+ s_dbname = STR2CSTR(dbname);
445
+ i_mode = FIX2INT(mode);
446
+
447
+ db = sqlite_open( s_dbname, i_mode, &errmsg );
448
+ if( db == NULL )
449
+ {
450
+ VALUE err = rb_str_new2( errmsg );
451
+ free( errmsg );
452
+
453
+ static_raise_db_error( -1, "%s", STR2CSTR( err ) );
454
+ }
455
+
456
+ hdb = ALLOC( SQLITE_RUBY_DATA );
457
+ hdb->db = db;
458
+ hdb->use_array = 0; /* default to FALSE */
459
+
460
+ v_db = Data_Wrap_Struct( klass, NULL, static_free_database_handle, hdb );
461
+
462
+ static_set_type_translation( v_db, Qfalse );
463
+
464
+ return v_db;
465
+ }
466
+
467
+
468
+ /**
469
+ * Closes an open database. No further methods should be invoked on the database
470
+ * after closing it.
471
+ */
472
+ static VALUE static_database_close( VALUE self )
473
+ {
474
+ SQLITE_RUBY_DATA *hdb;
475
+
476
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
477
+ if( hdb->db != NULL )
478
+ {
479
+ sqlite_close( hdb->db );
480
+ hdb->db = NULL;
481
+ }
482
+
483
+ return Qnil;
484
+ }
485
+
486
+
487
+ /**
488
+ * This is the base method used for querying the database. You will rarely use this method
489
+ * directly; rather, you should use the #execute method, instead. The +sql+ parameter is
490
+ * the text of the sql to execute, +callback+ is a proc object to be invoked for each row
491
+ * of the result set, and +parm+ is an application-specific cookie value that will be passed to
492
+ * the +callback+.
493
+ */
494
+ static VALUE static_database_exec( VALUE self,
495
+ VALUE sql,
496
+ VALUE callback,
497
+ VALUE parm )
498
+ {
499
+ SQLITE_RUBY_DATA *hdb;
500
+ SQLITE_RUBY_CALLBACK hook;
501
+ char *s_sql;
502
+ int i;
503
+ char *err = NULL;
504
+ VALUE v_err;
505
+
506
+ Check_Type( sql, T_STRING );
507
+ s_sql = STR2CSTR(sql);
508
+
509
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
510
+ if( hdb->db == NULL )
511
+ static_raise_db_error( -1, "attempt to access a closed database" );
512
+
513
+ hook.callback = callback;
514
+ hook.arg = parm;
515
+ hook.built_columns = 0;
516
+ hook.columns = Qnil;
517
+ hook.self = hdb;
518
+ hook.do_translate = ( rb_iv_get( self, "@type_translation" ) == Qtrue );
519
+
520
+ if( static_pragma_enabled( hdb->db, "show_datatypes" ) )
521
+ {
522
+ hook.types = rb_hash_new();
523
+ }
524
+ else
525
+ {
526
+ hook.types = Qnil;
527
+ hook.do_translate = 0; /* show_datatypes must be anbled for type translation */
528
+ }
529
+
530
+ i = sqlite_exec( hdb->db,
531
+ s_sql,
532
+ static_ruby_sqlite_callback,
533
+ &hook,
534
+ &err );
535
+
536
+ if( err != 0 )
537
+ {
538
+ v_err = rb_str_new2( err );
539
+ free( err );
540
+ }
541
+
542
+ switch( i )
543
+ {
544
+ case SQLITE_OK:
545
+ case SQLITE_ABORT:
546
+ break;
547
+ default:
548
+ static_raise_db_error( i, "%s", STR2CSTR(v_err) );
549
+ }
550
+
551
+ return INT2FIX(0);
552
+ }
553
+
554
+
555
+ /**
556
+ * Returns the key value of the last inserted row.
557
+ */
558
+ static VALUE static_last_insert_rowid( VALUE self )
559
+ {
560
+ SQLITE_RUBY_DATA *hdb;
561
+
562
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
563
+
564
+ if( hdb->db == NULL )
565
+ static_raise_db_error( -1, "attempt to access a closed database" );
566
+
567
+ return INT2FIX( sqlite_last_insert_rowid( hdb->db ) );
568
+ }
569
+
570
+
571
+ /**
572
+ * Returns the number of rows that were affected by the last query.
573
+ */
574
+ static VALUE static_changes( VALUE self )
575
+ {
576
+ SQLITE_RUBY_DATA *hdb;
577
+
578
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
579
+
580
+ if( hdb->db == NULL )
581
+ static_raise_db_error( -1, "attempt to access a closed database" );
582
+
583
+ return INT2FIX( sqlite_changes( hdb->db ) );
584
+ }
585
+
586
+
587
+ /**
588
+ * Interrupts the currently executing query, causing it to abort. If there
589
+ * is no current query, this does nothing.
590
+ */
591
+ static VALUE static_interrupt( VALUE self )
592
+ {
593
+ SQLITE_RUBY_DATA *hdb;
594
+
595
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
596
+
597
+ if( hdb->db == NULL )
598
+ static_raise_db_error( -1, "attempt to access a closed database" );
599
+
600
+ sqlite_interrupt( hdb->db );
601
+
602
+ return Qnil;
603
+ }
604
+
605
+
606
+ /**
607
+ * Queries whether or not the given SQL statement is complete or not.
608
+ * This is primarly useful in interactive environments where you are
609
+ * prompting the user for a query, line-by-line.
610
+ */
611
+ static VALUE static_complete( VALUE self,
612
+ VALUE sql )
613
+ {
614
+ Check_Type( sql, T_STRING );
615
+
616
+ return ( sqlite_complete( STR2CSTR( sql ) ) ? Qtrue : Qfalse );
617
+ }
618
+
619
+ /**
620
+ * Causes the database instance to use an array to represent rows
621
+ * in query results, if 'boolean' is not Qnil or Qfalse.
622
+ */
623
+ static VALUE static_set_use_array( VALUE self, VALUE boolean )
624
+ {
625
+ int use_array = RTEST( boolean );
626
+ SQLITE_RUBY_DATA *hdb;
627
+
628
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
629
+ hdb->use_array = use_array;
630
+
631
+ return boolean;
632
+ }
633
+
634
+ /**
635
+ * Queries the database instance to determine whether or not arrays
636
+ * are being used to represent rows in query results.
637
+ */
638
+ static VALUE static_is_use_array( VALUE self )
639
+ {
640
+ SQLITE_RUBY_DATA *hdb;
641
+
642
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
643
+ return ( hdb->use_array ? Qtrue : Qfalse );
644
+ }
645
+
646
+ /**
647
+ * Defines a custom SQL function with the given name and expected parameter count.
648
+ * The +callback+ must be a proc object, which will be invoked for each row of the
649
+ * result set. The +parm+ will be passed to the callback as well.
650
+ */
651
+ static VALUE static_create_function( VALUE self,
652
+ VALUE name,
653
+ VALUE argc,
654
+ VALUE callback,
655
+ VALUE parm )
656
+ {
657
+ SQLITE_RUBY_DATA *hdb;
658
+ SQLITE_CUSTOM_FUNCTION_CB *data;
659
+ char *s_name;
660
+ int i_argc;
661
+ int rc;
662
+
663
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
664
+ s_name = STR2CSTR( name );
665
+ i_argc = FIX2INT( argc );
666
+
667
+ if( hdb->db == NULL )
668
+ static_raise_db_error( -1, "attempt to access a closed database" );
669
+
670
+ data = ALLOC( SQLITE_CUSTOM_FUNCTION_CB );
671
+ data->callback = callback;
672
+ data->arg = parm;
673
+
674
+ rc = sqlite_create_function( hdb->db,
675
+ s_name,
676
+ i_argc,
677
+ static_custom_function_callback,
678
+ data );
679
+
680
+ if( rc != 0 )
681
+ static_raise_db_error( rc, "error registering custom function" );
682
+
683
+ return Qnil;
684
+ }
685
+
686
+
687
+ /**
688
+ * Defines a custom aggregate SQL function with the given name and argument count
689
+ * (+argc+). The +step+ parameter must be a proc object, which will be called for
690
+ * each iteration during the processing of the aggregate. The +finalize+ parameter
691
+ * must also be a proc object, and is called at the end of the processing of the
692
+ * aggreate. The +parm+ parameter will be passed to both callbacks.
693
+ */
694
+ static VALUE static_create_aggregate( VALUE self,
695
+ VALUE name,
696
+ VALUE argc,
697
+ VALUE step,
698
+ VALUE finalize,
699
+ VALUE parm )
700
+ {
701
+ SQLITE_RUBY_DATA *hdb;
702
+ SQLITE_CUSTOM_FUNCTION_CB *data;
703
+ char *s_name;
704
+ int i_argc;
705
+ int rc;
706
+
707
+ Data_Get_Struct( self, SQLITE_RUBY_DATA, hdb );
708
+ s_name = STR2CSTR( name );
709
+ i_argc = FIX2INT( argc );
710
+
711
+ if( hdb->db == NULL )
712
+ static_raise_db_error( -1, "attempt to access a closed database" );
713
+
714
+ data = ALLOC( SQLITE_CUSTOM_FUNCTION_CB );
715
+ data->callback = step;
716
+ data->finalize = finalize;
717
+ data->arg = parm;
718
+
719
+ rc = sqlite_create_aggregate( hdb->db,
720
+ s_name,
721
+ i_argc,
722
+ static_custom_aggregate_callback,
723
+ static_custom_finalize_callback,
724
+ data );
725
+
726
+ if( rc != 0 )
727
+ static_raise_db_error( rc, "error registering custom function" );
728
+
729
+ return Qnil;
730
+ }
731
+
732
+
733
+ /**
734
+ * Returns the number of rows in the aggregate context.
735
+ */
736
+ static VALUE static_aggregate_count( VALUE self )
737
+ {
738
+ sqlite_func *ctx;
739
+
740
+ Data_Get_Struct( self, sqlite_func, ctx );
741
+
742
+ return INT2FIX( sqlite_aggregate_count( ctx ) );
743
+ }
744
+
745
+
746
+ /**
747
+ * Returns the properties attribute of the aggregate context. This will always
748
+ * be a Hash object, which your custom functions may use to accumulate information
749
+ * into.
750
+ */
751
+ static VALUE static_get_properties( VALUE self )
752
+ {
753
+ sqlite_func *ctx;
754
+
755
+ Data_Get_Struct( self, sqlite_func, ctx );
756
+
757
+ return *(VALUE*)sqlite_aggregate_context( ctx, sizeof( VALUE ) );
758
+ }
759
+
760
+ /**
761
+ * Query whether or not the database is doing automatic type translation between
762
+ * the SQLite type (always a string) and the corresponding Ruby type.
763
+ */
764
+ static VALUE static_is_doing_type_translation( VALUE self )
765
+ {
766
+ return rb_iv_get( self, "@type_translation" );
767
+ }
768
+
769
+ /**
770
+ * Specify whether or not the database should do automatic type translation.
771
+ */
772
+ static VALUE static_set_type_translation( VALUE self, VALUE value )
773
+ {
774
+ if( value == Qnil || value == Qfalse )
775
+ {
776
+ value = Qfalse;
777
+ }
778
+ else
779
+ {
780
+ value = Qtrue;
781
+ }
782
+
783
+ return rb_iv_set( self, "@type_translation", value );
784
+ }
785
+
786
+ static void static_configure_exception_classes()
787
+ {
788
+ int i;
789
+
790
+ for( i = 1; g_sqlite_exceptions[ i ].name != NULL; i++ )
791
+ {
792
+ char name[ 128 ];
793
+
794
+ sprintf( name, "%sException", g_sqlite_exceptions[ i ].name );
795
+ g_sqlite_exceptions[ i ].object = rb_define_class_under( mSQLite, name, cSQLiteException );
796
+ }
797
+ }
798
+
799
+ static void static_raise_db_error( int code, char *msg, ... )
800
+ {
801
+ va_list args;
802
+ char message[ 2048 ];
803
+ VALUE exc;
804
+
805
+ va_start( args, msg );
806
+ vsnprintf( message, sizeof( message ), msg, args );
807
+ va_end( args );
808
+
809
+ exc = ( code <= 0 ? cSQLiteException : g_sqlite_exceptions[ code ].object );
810
+
811
+ rb_raise( exc, message );
812
+ }
813
+
814
+ void Init__sqlite()
815
+ {
816
+ VALUE version;
817
+
818
+ mSQLite = rb_define_module( "SQLite" );
819
+
820
+ idCallMethod = rb_intern( "call" );
821
+ idInstanceEvalMethod = rb_intern("instance_eval");
822
+ idTranslate = rb_intern("translate");
823
+ idFields = rb_intern("fields");
824
+ idFieldsEqual = rb_intern("fields=");
825
+
826
+ cSQLite = rb_define_class_under( mSQLite, "Database", rb_cObject );
827
+ cSQLiteException = rb_define_class_under( mSQLite, "DatabaseException", rb_eStandardError );
828
+ cSQLiteQueryContext = rb_define_class_under( mSQLite, "QueryContext", rb_cHash );
829
+ cSQLiteTypeTranslator = rb_define_class_under( mSQLite, "TypeTranslator", rb_cObject );
830
+
831
+ static_configure_exception_classes();
832
+
833
+ rb_define_singleton_method( cSQLite, "new", static_database_new, 2 );
834
+
835
+ rb_define_method( cSQLite, "close", static_database_close, 0 );
836
+ rb_define_method( cSQLite, "exec", static_database_exec, 3 );
837
+ rb_define_method( cSQLite, "last_insert_rowid", static_last_insert_rowid, 0 );
838
+ rb_define_method( cSQLite, "changes", static_changes, 0 );
839
+ rb_define_method( cSQLite, "interrupt", static_interrupt, 0 );
840
+ rb_define_method( cSQLite, "complete?", static_complete, 1 );
841
+ rb_define_method( cSQLite, "create_function", static_create_function, 4 );
842
+ rb_define_method( cSQLite, "create_aggregate", static_create_aggregate, 5 );
843
+ rb_define_method( cSQLite, "type_translation?", static_is_doing_type_translation, 0 );
844
+ rb_define_method( cSQLite, "type_translation=", static_set_type_translation, 1 );
845
+ rb_define_method( cSQLite, "use_array=", static_set_use_array, 1 );
846
+ rb_define_method( cSQLite, "use_array?", static_is_use_array, 0 );
847
+
848
+ rb_define_const( cSQLite, "VERSION", rb_str_new2( sqlite_libversion() ) );
849
+ rb_define_const( cSQLite, "ENCODING", rb_str_new2( sqlite_libencoding() ) );
850
+
851
+ version = rb_ary_new();
852
+ rb_ary_push( version, INT2FIX( LIB_VERSION_MAJOR ) );
853
+ rb_ary_push( version, INT2FIX( LIB_VERSION_MINOR ) );
854
+ rb_ary_push( version, INT2FIX( LIB_VERSION_TINY ) );
855
+ rb_define_const( mSQLite, "LIB_VERSION", version );
856
+
857
+ oSQLiteQueryAbort = rb_funcall( rb_cObject, rb_intern( "new" ), 0 );
858
+ rb_define_const( mSQLite, "ABORT", oSQLiteQueryAbort );
859
+
860
+ rb_define_method( cSQLiteQueryContext, "aggregate_count", static_aggregate_count, 0 );
861
+ rb_define_method( cSQLiteQueryContext, "properties", static_get_properties, 0 );
862
+ }