rdo-sqlite 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.so
19
+ *.bundle
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rdo-postgres.gemspec
4
+ gemspec
5
+
6
+ # allow a local version of RDO to be used during dev
7
+ if ENV["RDO_PATH"]
8
+ gem 'rdo', path: ENV["RDO_PATH"]
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright © 2012 Chris Corbyn.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # RDO SQLite3 Driver
2
+
3
+ This is the SQLite3 driver for [RDO—Ruby Data Objects]
4
+ (https://github.com/d11wtq/rdo).
5
+
6
+ Refer to the RDO project [README](https://github.com/d11wtq/rdo) for usage
7
+ information.
8
+
9
+ ## Installation
10
+
11
+ Via rubygems:
12
+
13
+ $ gem install rdo-sqlite
14
+
15
+ Or add the following line to your application's Gemfile:
16
+
17
+ gem "rdo-sqlite"
18
+
19
+ And install with Bundler:
20
+
21
+ $ bundle install
22
+
23
+ ## Usage
24
+
25
+ The registered URI schemes are sqlite: and sqlite3:
26
+
27
+ ``` ruby
28
+ require "rdo"
29
+ require "rdo-sqlite"
30
+
31
+ # use an in-memory database :memory:
32
+ db = RDO.open("sqlite::memory:")
33
+
34
+ # use a temporary file for the database (automatically deleted once closed)
35
+ db = RDO.open("sqlite:")
36
+
37
+ # use a relative path to a database (will be created if it doesn't exist)
38
+ db = RDO.open("sqlite:some/path/to/your.db")
39
+
40
+ # use an absolute path to a database
41
+ db = RDO.open("sqlite:/absolute/path/to/your.db")
42
+ ```
43
+
44
+ ## Type casting and bind parameters
45
+
46
+ SQLite, being a very basic database only has limited type support. Without
47
+ going into the whole discussion about SQLite's "type affinity" and how it
48
+ will effectively store anything in any column declared as any type, know that
49
+ the only internal types it actually stores are:
50
+
51
+ - NULL, which converts to nil in Ruby
52
+ - TEXT, which converts to a UTF-8 encoded String in Ruby
53
+ - INTEGER, which converts to a Fixnum in Ruby
54
+ - REAL, which converts to a Float in Ruby
55
+ - BLOB, which converts to a binary String in Ruby
56
+
57
+ If you have fields storing date strings etc, they are just Text, so are
58
+ returned as Strings, which you need to convert by hand. SQLite has no actual
59
+ DATE type, even if its date functions operate on strings formatted correctly.
60
+
61
+ ### Boolean types
62
+
63
+ Because defining fields as BOOLEAN and storing integer 0 or 1 in them is
64
+ common, rdo-sqlite will convert boolean bind parameters to 0 or 1. If you
65
+ actually want to store the String 'true' or 'false', you will need to
66
+ convert it to a String first.
67
+
68
+ ### Character encoding
69
+
70
+ SQLite does not allow the encoding of an existing database to be changed. It
71
+ only supports two encodings: UTF-8 and UTF-16. rdo-sqlite currently just
72
+ assumes UTF-8 encoding.
73
+
74
+ ## Contributing
75
+
76
+ If you find any bugs, please send a pull request if you think you can
77
+ fix it, or file in an issue in the issue tracker.
78
+
79
+ When sending pull requests, please use topic branches—don't send a pull
80
+ request from the master branch of your fork, as that may change
81
+ unintentionally.
82
+
83
+ Contributors will be credited in this README.
84
+
85
+ ## Copyright & Licensing
86
+
87
+ Written by Chris Corbyn.
88
+
89
+ Licensed under the MIT license. See the LICENSE file for full details.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "rake/extensiontask"
4
+
5
+ Rake::ExtensionTask.new('rdo_sqlite') do |ext|
6
+ ext.lib_dir = File.join('lib', 'rdo_sqlite')
7
+ end
8
+
9
+ desc "Run the full RSpec suite"
10
+ RSpec::Core::RakeTask.new('spec') do |t|
11
+ t.pattern = 'spec/'
12
+ end
13
+
14
+ Rake::Task['spec'].prerequisites << :compile
@@ -0,0 +1,99 @@
1
+ /*
2
+ * RDO SQLite3 Driver.
3
+ * Copyright © 2012 Chris Corbyn.
4
+ *
5
+ * See LICENSE file for details.
6
+ */
7
+
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include "driver.h"
11
+ #include "macros.h"
12
+ #include "statements.h"
13
+
14
+ /** Free memory associated with the driver during GC */
15
+ static void rdo_sqlite_driver_free(RDOSQLiteDriver * driver) {
16
+ sqlite3_close(driver->db);
17
+ free(driver);
18
+ }
19
+
20
+ /** Wrap the RDOSQLiteDriver struct with the new instance */
21
+ static VALUE rdo_sqlite_driver_allocate(VALUE klass) {
22
+ RDOSQLiteDriver * driver = malloc(sizeof(RDOSQLiteDriver));
23
+ driver->db = NULL;
24
+ driver->is_open = 0;
25
+
26
+ return Data_Wrap_Struct(klass, 0, rdo_sqlite_driver_free, driver);
27
+ }
28
+
29
+ /** Opens a database */
30
+ static VALUE rdo_sqlite_driver_open(VALUE self) {
31
+ RDOSQLiteDriver * driver;
32
+ Data_Get_Struct(self, RDOSQLiteDriver, driver);
33
+
34
+ if (driver->is_open) {
35
+ return Qtrue;
36
+ }
37
+
38
+ if (sqlite3_open_v2(
39
+ RSTRING_PTR(rb_funcall(self, rb_intern("filename"), 0)),
40
+ &(driver->db),
41
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) {
42
+ RDO_ERROR("SQLite3 database open failed: %s", sqlite3_errmsg(driver->db));
43
+ } else {
44
+ driver->is_open = 1;
45
+ }
46
+
47
+ return Qtrue;
48
+ }
49
+
50
+ /** Checks if the database file is open */
51
+ static VALUE rdo_sqlite_driver_open_p(VALUE self) {
52
+ RDOSQLiteDriver * driver;
53
+ Data_Get_Struct(self, RDOSQLiteDriver, driver);
54
+ return driver->is_open ? Qtrue : Qfalse;
55
+ }
56
+
57
+ /** Close the database and free memory */
58
+ static VALUE rdo_sqlite_driver_close(VALUE self) {
59
+ RDOSQLiteDriver * driver;
60
+ Data_Get_Struct(self, RDOSQLiteDriver, driver);
61
+
62
+ sqlite3_close(driver->db);
63
+ driver->db = NULL;
64
+ driver->is_open = 0;
65
+
66
+ return Qtrue;
67
+ }
68
+
69
+ /** Create a new prepared statement for cmd */
70
+ static VALUE rdo_sqlite_driver_prepare(VALUE self, VALUE cmd) {
71
+ return RDO_STATEMENT(rdo_sqlite_statement_executor_new(self, cmd));
72
+ }
73
+
74
+ /** Quote a string literal for interpolation into a statement */
75
+ static VALUE rdo_sqlite_driver_quote(VALUE self, VALUE str) {
76
+ Check_Type(str, T_STRING);
77
+ char * quoted = sqlite3_mprintf("%q", RSTRING_PTR(str));
78
+ VALUE new_str = rb_str_new2(quoted);
79
+ sqlite3_free(quoted);
80
+ return new_str;
81
+ }
82
+
83
+ /** Initialize driver class */
84
+ void Init_rdo_sqlite_driver(void) {
85
+ rb_require("rdo");
86
+ rb_require("rdo/sqlite/driver");
87
+
88
+ VALUE cSQLiteDriver = rb_path2class("RDO::SQLite::Driver");
89
+
90
+ rb_define_alloc_func(cSQLiteDriver, rdo_sqlite_driver_allocate);
91
+
92
+ rb_define_method(cSQLiteDriver, "open", rdo_sqlite_driver_open, 0);
93
+ rb_define_method(cSQLiteDriver, "open?", rdo_sqlite_driver_open_p, 0);
94
+ rb_define_method(cSQLiteDriver, "close", rdo_sqlite_driver_close, 0);
95
+ rb_define_method(cSQLiteDriver, "prepare", rdo_sqlite_driver_prepare, 1);
96
+ rb_define_method(cSQLiteDriver, "quote", rdo_sqlite_driver_quote, 1);
97
+
98
+ Init_rdo_sqlite_statements();
99
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ * RDO SQLite3 Driver.
3
+ * Copyright © 2012 Chris Corbyn.
4
+ *
5
+ * See LICENSE file for details.
6
+ */
7
+
8
+ #include <ruby.h>
9
+ #include <sqlite3.h>
10
+
11
+ /** Struct wrapped by RDO::SQLite::Driver class */
12
+ typedef struct {
13
+ sqlite3 * db;
14
+ int is_open;
15
+ } RDOSQLiteDriver;
16
+
17
+ /** Called during extension initialization to create the Driver class */
18
+ void Init_rdo_sqlite_driver(void);
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require "mkmf"
4
+
5
+ if ENV["CC"]
6
+ RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"]
7
+ end
8
+
9
+ def have_build_env
10
+ [
11
+ have_library("sqlite3"),
12
+ have_header("sqlite3.h")
13
+ ].all?
14
+ end
15
+
16
+ dir_config("sqlite")
17
+
18
+ unless have_build_env
19
+ puts "Unable to find sqlite3 libraries and headers. Not building."
20
+ exit(1)
21
+ end
22
+
23
+ create_makefile("rdo_sqlite/rdo_sqlite")
@@ -0,0 +1,193 @@
1
+ /*
2
+ * RDO—Ruby Data Objects.
3
+ * Copyright © 2012 Chris Corbyn.
4
+ *
5
+ * See LICENSE file for details.
6
+ */
7
+
8
+ /** -------------------------------------------------------------------------
9
+ * These macros are for use by RDO driver developers.
10
+ *
11
+ * They simplify the logic needed when converting types provided by the RDBMS
12
+ * into their equivalent Ruby types.
13
+ *
14
+ * All of these macros take a C string and return a Ruby VALUE.
15
+ *
16
+ * The actual logic for many of the conversions is handled in RDO::Util, which
17
+ * is written in Ruby.
18
+ * --------------------------------------------------------------------------
19
+ */
20
+
21
+ #include <ruby.h>
22
+ #include <ruby/encoding.h>
23
+
24
+ /**
25
+ * Convenience to call #to_s on any Ruby object.
26
+ */
27
+ #define RDO_OBJ_TO_S(obj) (rb_funcall(obj, rb_intern("to_s"), 0))
28
+
29
+ /**
30
+ * Raise an RDO::Exception with the given msg format and any number of parameters.
31
+ *
32
+ * @param (char *) msg
33
+ * a format string passed to rb_raise()
34
+ *
35
+ * @param (void *) ...
36
+ * args used to interpolate the error message
37
+ */
38
+ #define RDO_ERROR(...) (rb_raise(rb_path2class("RDO::Exception"), __VA_ARGS__))
39
+
40
+ /**
41
+ * Factory to return a new RDO::Result for an Enumerable object of tuples.
42
+ *
43
+ * @param VALUE (Enumerable) tuples
44
+ * an object that knows how to iterate all tuples
45
+ *
46
+ * @param VALUE (Hash)
47
+ * an optional hash of query info.
48
+ *
49
+ * @return VALUE (RDO::Result)
50
+ * a new Result object
51
+ */
52
+ #define RDO_RESULT(tuples, info) \
53
+ (rb_funcall(rb_path2class("RDO::Result"), rb_intern("new"), 2, tuples, info))
54
+
55
+ /**
56
+ * Wrap the given StatementExecutor in a RDO::Statement.
57
+ *
58
+ * @param VALUE
59
+ * any object that responds to #command and #execute
60
+ *
61
+ * @return VALUE
62
+ * an RDO::Statement
63
+ */
64
+ #define RDO_STATEMENT(executor) \
65
+ (rb_funcall(rb_path2class("RDO::Statement"), rb_intern("new"), 1, executor))
66
+
67
+ /**
68
+ * Convert a C string to a ruby String.
69
+ *
70
+ * @param (char *) s
71
+ * a C string that is valid in the default encoding
72
+ *
73
+ * @param (size_t) len
74
+ * the length of the string
75
+ *
76
+ * @return VALUE (String)
77
+ * a Ruby String
78
+ */
79
+ #define RDO_STRING(s, len, enc) \
80
+ (rb_enc_associate_index(rb_str_new(s, len), enc > 0 ? enc : 0))
81
+
82
+ /**
83
+ * Convert a C string to a ruby String, assuming possible NULL bytes.
84
+ *
85
+ * @param (char *) s
86
+ * a C string, possibly containing nulls
87
+ *
88
+ * @param (size_t) len
89
+ * the length of the string
90
+ *
91
+ * @return VALUE (String)
92
+ * a Ruby String
93
+ */
94
+ #define RDO_BINARY_STRING(s, len) (rb_str_new(s, len))
95
+
96
+ /**
97
+ * Convert a C string to a Fixnum.
98
+ */
99
+ #define RDO_FIXNUM(s) (rb_cstr2inum(s, 10))
100
+
101
+ /**
102
+ * Convert a C string to a Float.
103
+ *
104
+ * This supports Infinity and NaN.
105
+ *
106
+ * @param (char *) s
107
+ * a C string representing a float (e.g. "1.234")
108
+ *
109
+ * @return VALUE (Float)
110
+ * a ruby Float
111
+ */
112
+ #define RDO_FLOAT(s) \
113
+ (rb_funcall(rb_path2class("RDO::Util"), \
114
+ rb_intern("float"), 1, rb_str_new2(s)))
115
+
116
+ /**
117
+ * Convert a C string representing a precision decimal into a BigDecimal.
118
+ *
119
+ * @param (char *) s
120
+ * a C string representing a decimal ("1.245")
121
+ *
122
+ * @return VALUE (BigDecimal)
123
+ * a BigDecimal representation of this string
124
+ *
125
+ * @example
126
+ * RDO_DECIMAL("1.234")
127
+ * => #<BigDecimal:7feb42b2b6e8,'0.1234E1',18(18)>
128
+ */
129
+ #define RDO_DECIMAL(s) \
130
+ (rb_funcall(rb_path2class("RDO::Util"), \
131
+ rb_intern("decimal"), 1, rb_str_new2(s)))
132
+
133
+ /**
134
+ * Convert a C string representing a date into a Date.
135
+ *
136
+ * @param (char *) s
137
+ * the C string with a parseable date
138
+ *
139
+ * @return VALUE (Date)
140
+ * a Date, exactly as was specified in the input
141
+ *
142
+ * @example
143
+ * RDO_DATE("431-09-22 BC")
144
+ * #<Date: -0430-09-22 ((1564265j,0s,0n),+0s,2299161j)>
145
+ */
146
+ #define RDO_DATE(s) \
147
+ (rb_funcall(rb_path2class("RDO::Util"), \
148
+ rb_intern("date"), 1, rb_str_new2(s)))
149
+
150
+ /**
151
+ * Convert a C string representing a date & time with no time zone into a DateTime.
152
+ *
153
+ * @param (char *) s
154
+ * the C string with the date & time provided
155
+ *
156
+ * @return VALUE (DateTime)
157
+ * a DateTime, assuming the system time zone
158
+ *
159
+ * @example
160
+ * RDO_DATE_TIME_WITHOUT_ZONE("2012-09-22 04:36:12")
161
+ * #<DateTime: 2012-09-22T04:36:12+10:00 ((2456192j,66972s,0n),+36000s,2299161j)>
162
+ */
163
+ #define RDO_DATE_TIME_WITHOUT_ZONE(s) \
164
+ (rb_funcall(rb_path2class("RDO::Util"), \
165
+ rb_intern("date_time_without_zone"), 1, rb_str_new2(s)))
166
+
167
+ /**
168
+ * Convert a C string representing a date & time that includes a time zone into a DateTime.
169
+ *
170
+ * @param (char *) s
171
+ * the C string with the date & time provided, including the time zone
172
+ *
173
+ * @return VALUE (DateTime)
174
+ * a DateTime, exactly as was specified in the input
175
+ *
176
+ * @example
177
+ * RDO_DATE_TIME_WITHOUT_ZONE("2012-09-22 04:36:12+10:00")
178
+ * #<DateTime: 2012-09-22T04:36:12+10:00 ((2456192j,66972s,0n),+36000s,2299161j)>
179
+ */
180
+ #define RDO_DATE_TIME_WITH_ZONE(s) \
181
+ (rb_funcall(rb_path2class("RDO::Util"), \
182
+ rb_intern("date_time_with_zone"), 1, rb_str_new2(s)))
183
+
184
+ /**
185
+ * Convert a boolean string to TrueClass/FalseClass.
186
+ *
187
+ * @param (char *) s
188
+ * a C string that is either 't', 'true', 'f' or 'false'
189
+ *
190
+ * @return VALUE (TrueClass, FalseClass)
191
+ * the boolean representation
192
+ */
193
+ #define RDO_BOOL(s) ((s[0] == 't') ? Qtrue : Qfalse)
@@ -0,0 +1,15 @@
1
+ /*
2
+ * RDO SQLite3 Driver.
3
+ * Copyright © 2012 Chris Corbyn.
4
+ *
5
+ * See LICENSE file for details.
6
+ */
7
+
8
+ #include <ruby.h>
9
+ #include "driver.h"
10
+
11
+ /** Extension initializer */
12
+ void Init_rdo_sqlite(void) {
13
+ rb_require("rdo");
14
+ Init_rdo_sqlite_driver();
15
+ }