rdo-sqlite 0.0.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 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
+ }