sqlite3 2.0.0-aarch64-linux-musl
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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/CHANGELOG.md +800 -0
- data/CONTRIBUTING.md +56 -0
- data/FAQ.md +388 -0
- data/INSTALLATION.md +267 -0
- data/LICENSE +23 -0
- data/README.md +181 -0
- data/dependencies.yml +13 -0
- data/ext/sqlite3/aggregator.c +270 -0
- data/ext/sqlite3/aggregator.h +10 -0
- data/ext/sqlite3/backup.c +190 -0
- data/ext/sqlite3/backup.h +15 -0
- data/ext/sqlite3/database.c +931 -0
- data/ext/sqlite3/database.h +22 -0
- data/ext/sqlite3/exception.c +117 -0
- data/ext/sqlite3/exception.h +10 -0
- data/ext/sqlite3/extconf.rb +284 -0
- data/ext/sqlite3/sqlite3.c +208 -0
- data/ext/sqlite3/sqlite3_ruby.h +48 -0
- data/ext/sqlite3/statement.c +667 -0
- data/ext/sqlite3/statement.h +16 -0
- data/ext/sqlite3/timespec.h +20 -0
- data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.1/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.2/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.3/sqlite3_native.so +0 -0
- data/lib/sqlite3/constants.rb +174 -0
- data/lib/sqlite3/database.rb +701 -0
- data/lib/sqlite3/errors.rb +60 -0
- data/lib/sqlite3/pragmas.rb +585 -0
- data/lib/sqlite3/resultset.rb +96 -0
- data/lib/sqlite3/statement.rb +190 -0
- data/lib/sqlite3/value.rb +54 -0
- data/lib/sqlite3/version.rb +3 -0
- data/lib/sqlite3.rb +17 -0
- metadata +101 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#ifndef SQLITE3_DATABASE_RUBY
|
2
|
+
#define SQLITE3_DATABASE_RUBY
|
3
|
+
|
4
|
+
#include <sqlite3_ruby.h>
|
5
|
+
|
6
|
+
struct _sqlite3Ruby {
|
7
|
+
sqlite3 *db;
|
8
|
+
VALUE busy_handler;
|
9
|
+
int stmt_timeout;
|
10
|
+
struct timespec stmt_deadline;
|
11
|
+
};
|
12
|
+
|
13
|
+
typedef struct _sqlite3Ruby sqlite3Ruby;
|
14
|
+
typedef sqlite3Ruby *sqlite3RubyPtr;
|
15
|
+
|
16
|
+
void init_sqlite3_database();
|
17
|
+
void set_sqlite3_func_result(sqlite3_context *ctx, VALUE result);
|
18
|
+
|
19
|
+
sqlite3RubyPtr sqlite3_database_unwrap(VALUE database);
|
20
|
+
VALUE sqlite3val2rb(sqlite3_value *val);
|
21
|
+
|
22
|
+
#endif
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#include <sqlite3_ruby.h>
|
2
|
+
|
3
|
+
void
|
4
|
+
rb_sqlite3_raise(sqlite3 *db, int status)
|
5
|
+
{
|
6
|
+
VALUE klass = Qnil;
|
7
|
+
|
8
|
+
/* Consider only lower 8 bits, to work correctly when
|
9
|
+
extended result codes are enabled. */
|
10
|
+
switch (status & 0xff) {
|
11
|
+
case SQLITE_OK:
|
12
|
+
return;
|
13
|
+
break;
|
14
|
+
case SQLITE_ERROR:
|
15
|
+
klass = rb_path2class("SQLite3::SQLException");
|
16
|
+
break;
|
17
|
+
case SQLITE_INTERNAL:
|
18
|
+
klass = rb_path2class("SQLite3::InternalException");
|
19
|
+
break;
|
20
|
+
case SQLITE_PERM:
|
21
|
+
klass = rb_path2class("SQLite3::PermissionException");
|
22
|
+
break;
|
23
|
+
case SQLITE_ABORT:
|
24
|
+
klass = rb_path2class("SQLite3::AbortException");
|
25
|
+
break;
|
26
|
+
case SQLITE_BUSY:
|
27
|
+
klass = rb_path2class("SQLite3::BusyException");
|
28
|
+
break;
|
29
|
+
case SQLITE_LOCKED:
|
30
|
+
klass = rb_path2class("SQLite3::LockedException");
|
31
|
+
break;
|
32
|
+
case SQLITE_NOMEM:
|
33
|
+
klass = rb_path2class("SQLite3::MemoryException");
|
34
|
+
break;
|
35
|
+
case SQLITE_READONLY:
|
36
|
+
klass = rb_path2class("SQLite3::ReadOnlyException");
|
37
|
+
break;
|
38
|
+
case SQLITE_INTERRUPT:
|
39
|
+
klass = rb_path2class("SQLite3::InterruptException");
|
40
|
+
break;
|
41
|
+
case SQLITE_IOERR:
|
42
|
+
klass = rb_path2class("SQLite3::IOException");
|
43
|
+
break;
|
44
|
+
case SQLITE_CORRUPT:
|
45
|
+
klass = rb_path2class("SQLite3::CorruptException");
|
46
|
+
break;
|
47
|
+
case SQLITE_NOTFOUND:
|
48
|
+
klass = rb_path2class("SQLite3::NotFoundException");
|
49
|
+
break;
|
50
|
+
case SQLITE_FULL:
|
51
|
+
klass = rb_path2class("SQLite3::FullException");
|
52
|
+
break;
|
53
|
+
case SQLITE_CANTOPEN:
|
54
|
+
klass = rb_path2class("SQLite3::CantOpenException");
|
55
|
+
break;
|
56
|
+
case SQLITE_PROTOCOL:
|
57
|
+
klass = rb_path2class("SQLite3::ProtocolException");
|
58
|
+
break;
|
59
|
+
case SQLITE_EMPTY:
|
60
|
+
klass = rb_path2class("SQLite3::EmptyException");
|
61
|
+
break;
|
62
|
+
case SQLITE_SCHEMA:
|
63
|
+
klass = rb_path2class("SQLite3::SchemaChangedException");
|
64
|
+
break;
|
65
|
+
case SQLITE_TOOBIG:
|
66
|
+
klass = rb_path2class("SQLite3::TooBigException");
|
67
|
+
break;
|
68
|
+
case SQLITE_CONSTRAINT:
|
69
|
+
klass = rb_path2class("SQLite3::ConstraintException");
|
70
|
+
break;
|
71
|
+
case SQLITE_MISMATCH:
|
72
|
+
klass = rb_path2class("SQLite3::MismatchException");
|
73
|
+
break;
|
74
|
+
case SQLITE_MISUSE:
|
75
|
+
klass = rb_path2class("SQLite3::MisuseException");
|
76
|
+
break;
|
77
|
+
case SQLITE_NOLFS:
|
78
|
+
klass = rb_path2class("SQLite3::UnsupportedException");
|
79
|
+
break;
|
80
|
+
case SQLITE_AUTH:
|
81
|
+
klass = rb_path2class("SQLite3::AuthorizationException");
|
82
|
+
break;
|
83
|
+
case SQLITE_FORMAT:
|
84
|
+
klass = rb_path2class("SQLite3::FormatException");
|
85
|
+
break;
|
86
|
+
case SQLITE_RANGE:
|
87
|
+
klass = rb_path2class("SQLite3::RangeException");
|
88
|
+
break;
|
89
|
+
case SQLITE_NOTADB:
|
90
|
+
klass = rb_path2class("SQLite3::NotADatabaseException");
|
91
|
+
break;
|
92
|
+
default:
|
93
|
+
klass = rb_path2class("SQLite3::Exception");
|
94
|
+
}
|
95
|
+
|
96
|
+
klass = rb_exc_new2(klass, sqlite3_errmsg(db));
|
97
|
+
rb_iv_set(klass, "@code", INT2FIX(status));
|
98
|
+
rb_exc_raise(klass);
|
99
|
+
}
|
100
|
+
|
101
|
+
/*
|
102
|
+
* accepts a sqlite3 error message as the final argument, which will be `sqlite3_free`d
|
103
|
+
*/
|
104
|
+
void
|
105
|
+
rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg)
|
106
|
+
{
|
107
|
+
VALUE exception;
|
108
|
+
|
109
|
+
if (status == SQLITE_OK) {
|
110
|
+
return;
|
111
|
+
}
|
112
|
+
|
113
|
+
exception = rb_exc_new2(rb_path2class("SQLite3::Exception"), msg);
|
114
|
+
sqlite3_free((void *)msg);
|
115
|
+
rb_iv_set(exception, "@code", INT2FIX(status));
|
116
|
+
rb_exc_raise(exception);
|
117
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#ifndef SQLITE3_EXCEPTION_RUBY
|
2
|
+
#define SQLITE3_EXCEPTION_RUBY
|
3
|
+
|
4
|
+
#define CHECK(_db, _status) rb_sqlite3_raise(_db, _status);
|
5
|
+
#define CHECK_MSG(_db, _status, _msg) rb_sqlite3_raise_msg(_db, _status, _msg);
|
6
|
+
|
7
|
+
void rb_sqlite3_raise(sqlite3 *db, int status);
|
8
|
+
void rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg);
|
9
|
+
|
10
|
+
#endif
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require "mkmf"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module Sqlite3
|
5
|
+
module ExtConf
|
6
|
+
ENV_ALLOWLIST = ["CC", "CFLAGS", "LDFLAGS", "LIBS", "CPPFLAGS", "LT_SYS_LIBRARY_PATH", "CPP"]
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def configure
|
10
|
+
configure_cross_compiler
|
11
|
+
|
12
|
+
if system_libraries?
|
13
|
+
message "Building sqlite3-ruby using system #{libname}.\n"
|
14
|
+
configure_system_libraries
|
15
|
+
else
|
16
|
+
message "Building sqlite3-ruby using packaged sqlite3.\n"
|
17
|
+
configure_packaged_libraries
|
18
|
+
end
|
19
|
+
|
20
|
+
configure_extension
|
21
|
+
|
22
|
+
create_makefile("sqlite3/sqlite3_native")
|
23
|
+
end
|
24
|
+
|
25
|
+
def configure_cross_compiler
|
26
|
+
RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
|
27
|
+
ENV["CC"] = RbConfig::CONFIG["CC"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def system_libraries?
|
31
|
+
sqlcipher? || enable_config("system-libraries")
|
32
|
+
end
|
33
|
+
|
34
|
+
def libname
|
35
|
+
sqlcipher? ? "sqlcipher" : "sqlite3"
|
36
|
+
end
|
37
|
+
|
38
|
+
def sqlcipher?
|
39
|
+
with_config("sqlcipher") ||
|
40
|
+
with_config("sqlcipher-dir") ||
|
41
|
+
with_config("sqlcipher-include") ||
|
42
|
+
with_config("sqlcipher-lib")
|
43
|
+
end
|
44
|
+
|
45
|
+
def configure_system_libraries
|
46
|
+
pkg_config(libname)
|
47
|
+
append_cppflags("-DUSING_SQLCIPHER") if sqlcipher?
|
48
|
+
end
|
49
|
+
|
50
|
+
def configure_packaged_libraries
|
51
|
+
minimal_recipe.tap do |recipe|
|
52
|
+
recipe.configure_options += [
|
53
|
+
"--enable-shared=no",
|
54
|
+
"--enable-static=yes",
|
55
|
+
"--enable-fts5"
|
56
|
+
]
|
57
|
+
ENV.to_h.tap do |env|
|
58
|
+
user_cflags = with_config("sqlite-cflags")
|
59
|
+
more_cflags = [
|
60
|
+
"-fPIC", # needed for linking the static library into a shared library
|
61
|
+
"-O2", # see https://github.com/sparklemotion/sqlite3-ruby/issues/335 for some benchmarks
|
62
|
+
"-fvisibility=hidden", # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
|
63
|
+
"-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
|
64
|
+
]
|
65
|
+
env["CFLAGS"] = [user_cflags, env["CFLAGS"], more_cflags].flatten.join(" ")
|
66
|
+
recipe.configure_options += env.select { |k, v| ENV_ALLOWLIST.include?(k) }
|
67
|
+
.map { |key, value| "#{key}=#{value.strip}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
unless File.exist?(File.join(recipe.target, recipe.host, recipe.name, recipe.version))
|
71
|
+
recipe.cook
|
72
|
+
end
|
73
|
+
recipe.activate
|
74
|
+
|
75
|
+
# on macos, pkg-config will not return --cflags without this
|
76
|
+
ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
|
77
|
+
|
78
|
+
# only needed for Ruby 3.1.3, see https://bugs.ruby-lang.org/issues/19233
|
79
|
+
RbConfig::CONFIG["PKG_CONFIG"] = config_string("PKG_CONFIG") || "pkg-config"
|
80
|
+
|
81
|
+
lib_path = File.join(recipe.path, "lib")
|
82
|
+
pcfile = File.join(lib_path, "pkgconfig", "sqlite3.pc")
|
83
|
+
abort_pkg_config("pkg_config") unless pkg_config(pcfile)
|
84
|
+
|
85
|
+
# see https://bugs.ruby-lang.org/issues/18490
|
86
|
+
ldflags = xpopen(["pkg-config", "--libs", "--static", pcfile], err: [:child, :out], &:read)
|
87
|
+
abort_pkg_config("xpopen") unless $?.success?
|
88
|
+
ldflags = ldflags.split
|
89
|
+
|
90
|
+
# see https://github.com/flavorjones/mini_portile/issues/118
|
91
|
+
"-L#{lib_path}".tap do |lib_path_flag|
|
92
|
+
ldflags.prepend(lib_path_flag) unless ldflags.include?(lib_path_flag)
|
93
|
+
end
|
94
|
+
|
95
|
+
ldflags.each { |ldflag| append_ldflags(ldflag) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def configure_extension
|
100
|
+
append_cflags("-fvisibility=hidden") # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
|
101
|
+
|
102
|
+
if find_header("sqlite3.h")
|
103
|
+
# noop
|
104
|
+
elsif sqlcipher? && find_header("sqlcipher/sqlite3.h")
|
105
|
+
append_cppflags("-DUSING_SQLCIPHER_INC_SUBDIR")
|
106
|
+
else
|
107
|
+
abort_could_not_find("sqlite3.h")
|
108
|
+
end
|
109
|
+
|
110
|
+
abort_could_not_find(libname) unless find_library(libname, "sqlite3_libversion_number", "sqlite3.h")
|
111
|
+
|
112
|
+
# Truffle Ruby doesn't support this yet:
|
113
|
+
# https://github.com/oracle/truffleruby/issues/3408
|
114
|
+
have_func("rb_enc_interned_str_cstr")
|
115
|
+
|
116
|
+
# Functions defined in 1.9 but not 1.8
|
117
|
+
have_func("rb_proc_arity")
|
118
|
+
|
119
|
+
# Functions defined in 2.1 but not 2.0
|
120
|
+
have_func("rb_integer_pack")
|
121
|
+
|
122
|
+
# These functions may not be defined
|
123
|
+
have_func("sqlite3_initialize")
|
124
|
+
have_func("sqlite3_backup_init")
|
125
|
+
have_func("sqlite3_column_database_name")
|
126
|
+
have_func("sqlite3_enable_load_extension")
|
127
|
+
have_func("sqlite3_load_extension")
|
128
|
+
|
129
|
+
unless have_func("sqlite3_open_v2") # https://www.sqlite.org/releaselog/3_5_0.html
|
130
|
+
abort("\nPlease use a version of SQLite3 >= 3.5.0\n\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
have_func("sqlite3_prepare_v2")
|
134
|
+
have_type("sqlite3_int64", "sqlite3.h")
|
135
|
+
have_type("sqlite3_uint64", "sqlite3.h")
|
136
|
+
end
|
137
|
+
|
138
|
+
def minimal_recipe
|
139
|
+
require "mini_portile2"
|
140
|
+
|
141
|
+
MiniPortile.new(libname, sqlite3_config[:version]).tap do |recipe|
|
142
|
+
if sqlite_source_dir
|
143
|
+
recipe.source_directory = sqlite_source_dir
|
144
|
+
else
|
145
|
+
recipe.files = sqlite3_config[:files]
|
146
|
+
recipe.target = File.join(package_root_dir, "ports")
|
147
|
+
recipe.patch_files = Dir[File.join(package_root_dir, "patches", "*.patch")].sort
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def package_root_dir
|
153
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
|
154
|
+
end
|
155
|
+
|
156
|
+
def sqlite3_config
|
157
|
+
mini_portile_config[:sqlite3]
|
158
|
+
end
|
159
|
+
|
160
|
+
def mini_portile_config
|
161
|
+
YAML.load_file(File.join(package_root_dir, "dependencies.yml"), symbolize_names: true)
|
162
|
+
end
|
163
|
+
|
164
|
+
def abort_could_not_find(missing)
|
165
|
+
abort("\nCould not find #{missing}.\nPlease visit https://github.com/sparklemotion/sqlite3-ruby for installation instructions.\n\n")
|
166
|
+
end
|
167
|
+
|
168
|
+
def abort_pkg_config(id)
|
169
|
+
abort("\nCould not configure the build properly (#{id}). Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n\n")
|
170
|
+
end
|
171
|
+
|
172
|
+
def cross_build?
|
173
|
+
enable_config("cross-build")
|
174
|
+
end
|
175
|
+
|
176
|
+
def sqlite_source_dir
|
177
|
+
arg_config("--with-sqlite-source-dir")
|
178
|
+
end
|
179
|
+
|
180
|
+
def download
|
181
|
+
minimal_recipe.download
|
182
|
+
end
|
183
|
+
|
184
|
+
def darwin?
|
185
|
+
RbConfig::CONFIG["target_os"].include?("darwin")
|
186
|
+
end
|
187
|
+
|
188
|
+
def print_help
|
189
|
+
print(<<~TEXT)
|
190
|
+
USAGE: ruby #{$PROGRAM_NAME} [options]
|
191
|
+
|
192
|
+
Flags that are always valid:
|
193
|
+
|
194
|
+
--disable-system-libraries
|
195
|
+
Use the packaged libraries, and ignore the system libraries.
|
196
|
+
(This is the default behavior.)
|
197
|
+
|
198
|
+
--enable-system-libraries
|
199
|
+
Use system libraries instead of building and using the packaged libraries.
|
200
|
+
|
201
|
+
--with-sqlcipher
|
202
|
+
Use libsqlcipher instead of libsqlite3.
|
203
|
+
(Implies `--enable-system-libraries`.)
|
204
|
+
|
205
|
+
--with-sqlite-source-dir=DIRECTORY
|
206
|
+
(dev only) Build sqlite from the source code in DIRECTORY
|
207
|
+
|
208
|
+
--help
|
209
|
+
Display this message.
|
210
|
+
|
211
|
+
|
212
|
+
Flags only used when using system libraries:
|
213
|
+
|
214
|
+
General (applying to all system libraries):
|
215
|
+
|
216
|
+
--with-opt-dir=DIRECTORY
|
217
|
+
Look for headers and libraries in DIRECTORY.
|
218
|
+
|
219
|
+
--with-opt-lib=DIRECTORY
|
220
|
+
Look for libraries in DIRECTORY.
|
221
|
+
|
222
|
+
--with-opt-include=DIRECTORY
|
223
|
+
Look for headers in DIRECTORY.
|
224
|
+
|
225
|
+
Related to sqlcipher:
|
226
|
+
|
227
|
+
--with-sqlcipher-dir=DIRECTORY
|
228
|
+
Look for sqlcipher headers and library in DIRECTORY.
|
229
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
230
|
+
|
231
|
+
--with-sqlcipher-lib=DIRECTORY
|
232
|
+
Look for sqlcipher library in DIRECTORY.
|
233
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
234
|
+
|
235
|
+
--with-sqlcipher-include=DIRECTORY
|
236
|
+
Look for sqlcipher headers in DIRECTORY.
|
237
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
238
|
+
|
239
|
+
|
240
|
+
Flags only used when building and using the packaged libraries:
|
241
|
+
|
242
|
+
--with-sqlite-cflags=CFLAGS
|
243
|
+
Explicitly pass compiler flags to the sqlite library build. These flags will
|
244
|
+
appear on the commandline before any flags set in the CFLAGS environment
|
245
|
+
variable. This is useful for setting compilation options in your project's
|
246
|
+
bundler config. See INSTALLATION.md for more information.
|
247
|
+
|
248
|
+
--enable-cross-build
|
249
|
+
Enable cross-build mode. (You probably do not want to set this manually.)
|
250
|
+
|
251
|
+
|
252
|
+
Environment variables used for compiling the gem's C extension:
|
253
|
+
|
254
|
+
CC
|
255
|
+
Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
|
256
|
+
|
257
|
+
|
258
|
+
Environment variables passed through to the compilation of sqlite:
|
259
|
+
|
260
|
+
CC
|
261
|
+
CPPFLAGS
|
262
|
+
CFLAGS
|
263
|
+
LDFLAGS
|
264
|
+
LIBS
|
265
|
+
LT_SYS_LIBRARY_PATH
|
266
|
+
CPP
|
267
|
+
|
268
|
+
TEXT
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
if arg_config("--help")
|
275
|
+
Sqlite3::ExtConf.print_help
|
276
|
+
exit!(0)
|
277
|
+
end
|
278
|
+
|
279
|
+
if arg_config("--download-dependencies")
|
280
|
+
Sqlite3::ExtConf.download
|
281
|
+
exit!(0)
|
282
|
+
end
|
283
|
+
|
284
|
+
Sqlite3::ExtConf.configure
|
@@ -0,0 +1,208 @@
|
|
1
|
+
#include <sqlite3_ruby.h>
|
2
|
+
|
3
|
+
VALUE mSqlite3;
|
4
|
+
VALUE cSqlite3Blob;
|
5
|
+
|
6
|
+
int
|
7
|
+
bignum_to_int64(VALUE value, sqlite3_int64 *result)
|
8
|
+
{
|
9
|
+
#ifdef HAVE_RB_INTEGER_PACK
|
10
|
+
const int nails = 0;
|
11
|
+
int t = rb_integer_pack(value, result, 1, sizeof(*result), nails,
|
12
|
+
INTEGER_PACK_NATIVE_BYTE_ORDER |
|
13
|
+
INTEGER_PACK_2COMP);
|
14
|
+
switch (t) {
|
15
|
+
case -2:
|
16
|
+
case +2:
|
17
|
+
return 0;
|
18
|
+
case +1:
|
19
|
+
if (!nails) {
|
20
|
+
if (*result < 0) { return 0; }
|
21
|
+
}
|
22
|
+
break;
|
23
|
+
case -1:
|
24
|
+
if (!nails) {
|
25
|
+
if (*result >= 0) { return 0; }
|
26
|
+
} else {
|
27
|
+
*result += INT64_MIN;
|
28
|
+
}
|
29
|
+
break;
|
30
|
+
}
|
31
|
+
return 1;
|
32
|
+
#else
|
33
|
+
# ifndef RBIGNUM_LEN
|
34
|
+
# define RBIGNUM_LEN(x) RBIGNUM(x)->len
|
35
|
+
# endif
|
36
|
+
const long len = RBIGNUM_LEN(value);
|
37
|
+
if (len == 0) {
|
38
|
+
*result = 0;
|
39
|
+
return 1;
|
40
|
+
}
|
41
|
+
if (len > 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) { return 0; }
|
42
|
+
if (len == 63 / (SIZEOF_BDIGITS * CHAR_BIT) + 1) {
|
43
|
+
const BDIGIT *digits = RBIGNUM_DIGITS(value);
|
44
|
+
BDIGIT blast = digits[len - 1];
|
45
|
+
BDIGIT bmax = (BDIGIT)1UL << (63 % (CHAR_BIT * SIZEOF_BDIGITS));
|
46
|
+
if (blast > bmax) { return 0; }
|
47
|
+
if (blast == bmax) {
|
48
|
+
if (RBIGNUM_POSITIVE_P(value)) {
|
49
|
+
return 0;
|
50
|
+
} else {
|
51
|
+
long i = len - 1;
|
52
|
+
while (i) {
|
53
|
+
if (digits[--i]) { return 0; }
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
*result = (sqlite3_int64)NUM2LL(value);
|
59
|
+
return 1;
|
60
|
+
#endif
|
61
|
+
}
|
62
|
+
|
63
|
+
static VALUE
|
64
|
+
libversion(VALUE UNUSED(klass))
|
65
|
+
{
|
66
|
+
return INT2NUM(sqlite3_libversion_number());
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE
|
70
|
+
using_sqlcipher(VALUE UNUSED(klass))
|
71
|
+
{
|
72
|
+
#ifdef USING_SQLCIPHER
|
73
|
+
return Qtrue;
|
74
|
+
#else
|
75
|
+
return Qfalse;
|
76
|
+
#endif
|
77
|
+
}
|
78
|
+
|
79
|
+
/* Returns the compile time setting of the SQLITE_THREADSAFE flag.
|
80
|
+
* See: https://www.sqlite.org/c3ref/threadsafe.html
|
81
|
+
*/
|
82
|
+
static VALUE
|
83
|
+
threadsafe_p(VALUE UNUSED(klass))
|
84
|
+
{
|
85
|
+
return INT2NUM(sqlite3_threadsafe());
|
86
|
+
}
|
87
|
+
|
88
|
+
/*
|
89
|
+
* call-seq:
|
90
|
+
* status(parameter) → Hash
|
91
|
+
* status(parameter, reset_flag = false) → Hash
|
92
|
+
*
|
93
|
+
* Queries the SQLite3 library for run-time status information. Passing a truthy +reset_flag+ will
|
94
|
+
* reset the highwater mark to the current value.
|
95
|
+
*
|
96
|
+
* [Parameters]
|
97
|
+
* - +parameter+ (Integer, SQLite3::Constants::Status): The status parameter to query.
|
98
|
+
* - +reset_flag+ (Boolean): Whether to reset the highwater mark. (default is +false+)
|
99
|
+
*
|
100
|
+
* [Returns]
|
101
|
+
* A Hash containing +:current+ and +:highwater+ keys for integer values.
|
102
|
+
*/
|
103
|
+
static VALUE
|
104
|
+
rb_sqlite3_status(int argc, VALUE *argv, VALUE klass)
|
105
|
+
{
|
106
|
+
VALUE opArg, resetFlagArg;
|
107
|
+
|
108
|
+
rb_scan_args(argc, argv, "11", &opArg, &resetFlagArg);
|
109
|
+
|
110
|
+
int op = NUM2INT(opArg);
|
111
|
+
bool resetFlag = RTEST(resetFlagArg);
|
112
|
+
|
113
|
+
int pCurrent = 0;
|
114
|
+
int pHighwater = 0;
|
115
|
+
sqlite3_status(op, &pCurrent, &pHighwater, resetFlag);
|
116
|
+
|
117
|
+
VALUE hash = rb_hash_new();
|
118
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("current")), INT2FIX(pCurrent));
|
119
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("highwater")), INT2FIX(pHighwater));
|
120
|
+
|
121
|
+
return hash;
|
122
|
+
}
|
123
|
+
|
124
|
+
void
|
125
|
+
init_sqlite3_constants(void)
|
126
|
+
{
|
127
|
+
VALUE mSqlite3Constants;
|
128
|
+
VALUE mSqlite3Open;
|
129
|
+
|
130
|
+
mSqlite3Constants = rb_define_module_under(mSqlite3, "Constants");
|
131
|
+
|
132
|
+
/* sqlite3_open_v2 flags for Database::new */
|
133
|
+
mSqlite3Open = rb_define_module_under(mSqlite3Constants, "Open");
|
134
|
+
|
135
|
+
/* symbols = IO.readlines('sqlite3.h').map { |n| /\A#define\s+(SQLITE_OPEN_\w+)\s/ =~ n && $1 }.compact
|
136
|
+
* pad = symbols.map(&:length).max - 9
|
137
|
+
* symbols.each { |s| printf %Q{ rb_define_const(mSqlite3Open, %-#{pad}s INT2FIX(#{s}));\n}, '"' + s[12..-1] + '",' }
|
138
|
+
*/
|
139
|
+
rb_define_const(mSqlite3Open, "READONLY", INT2FIX(SQLITE_OPEN_READONLY));
|
140
|
+
rb_define_const(mSqlite3Open, "READWRITE", INT2FIX(SQLITE_OPEN_READWRITE));
|
141
|
+
rb_define_const(mSqlite3Open, "CREATE", INT2FIX(SQLITE_OPEN_CREATE));
|
142
|
+
rb_define_const(mSqlite3Open, "DELETEONCLOSE", INT2FIX(SQLITE_OPEN_DELETEONCLOSE));
|
143
|
+
rb_define_const(mSqlite3Open, "EXCLUSIVE", INT2FIX(SQLITE_OPEN_EXCLUSIVE));
|
144
|
+
rb_define_const(mSqlite3Open, "MAIN_DB", INT2FIX(SQLITE_OPEN_MAIN_DB));
|
145
|
+
rb_define_const(mSqlite3Open, "TEMP_DB", INT2FIX(SQLITE_OPEN_TEMP_DB));
|
146
|
+
rb_define_const(mSqlite3Open, "TRANSIENT_DB", INT2FIX(SQLITE_OPEN_TRANSIENT_DB));
|
147
|
+
rb_define_const(mSqlite3Open, "MAIN_JOURNAL", INT2FIX(SQLITE_OPEN_MAIN_JOURNAL));
|
148
|
+
rb_define_const(mSqlite3Open, "TEMP_JOURNAL", INT2FIX(SQLITE_OPEN_TEMP_JOURNAL));
|
149
|
+
rb_define_const(mSqlite3Open, "SUBJOURNAL", INT2FIX(SQLITE_OPEN_SUBJOURNAL));
|
150
|
+
rb_define_const(mSqlite3Open, "MASTER_JOURNAL",
|
151
|
+
INT2FIX(SQLITE_OPEN_MASTER_JOURNAL)); /* pre-3.33.0 */
|
152
|
+
rb_define_const(mSqlite3Open, "SUPER_JOURNAL", INT2FIX(SQLITE_OPEN_MASTER_JOURNAL));
|
153
|
+
rb_define_const(mSqlite3Open, "NOMUTEX", INT2FIX(SQLITE_OPEN_NOMUTEX));
|
154
|
+
rb_define_const(mSqlite3Open, "FULLMUTEX", INT2FIX(SQLITE_OPEN_FULLMUTEX));
|
155
|
+
#ifdef SQLITE_OPEN_AUTOPROXY
|
156
|
+
/* SQLITE_VERSION_NUMBER>=3007002 */
|
157
|
+
rb_define_const(mSqlite3Open, "AUTOPROXY", INT2FIX(SQLITE_OPEN_AUTOPROXY));
|
158
|
+
rb_define_const(mSqlite3Open, "SHAREDCACHE", INT2FIX(SQLITE_OPEN_SHAREDCACHE));
|
159
|
+
rb_define_const(mSqlite3Open, "PRIVATECACHE", INT2FIX(SQLITE_OPEN_PRIVATECACHE));
|
160
|
+
rb_define_const(mSqlite3Open, "WAL", INT2FIX(SQLITE_OPEN_WAL));
|
161
|
+
#endif
|
162
|
+
#ifdef SQLITE_OPEN_URI
|
163
|
+
/* SQLITE_VERSION_NUMBER>=3007007 */
|
164
|
+
rb_define_const(mSqlite3Open, "URI", INT2FIX(SQLITE_OPEN_URI));
|
165
|
+
#endif
|
166
|
+
#ifdef SQLITE_OPEN_MEMORY
|
167
|
+
/* SQLITE_VERSION_NUMBER>=3007013 */
|
168
|
+
rb_define_const(mSqlite3Open, "MEMORY", INT2FIX(SQLITE_OPEN_MEMORY));
|
169
|
+
#endif
|
170
|
+
}
|
171
|
+
|
172
|
+
RUBY_FUNC_EXPORTED
|
173
|
+
void
|
174
|
+
Init_sqlite3_native(void)
|
175
|
+
{
|
176
|
+
/*
|
177
|
+
* SQLite3 is a wrapper around the popular database
|
178
|
+
* sqlite[http://sqlite.org].
|
179
|
+
*
|
180
|
+
* For an example of usage, see SQLite3::Database.
|
181
|
+
*/
|
182
|
+
mSqlite3 = rb_define_module("SQLite3");
|
183
|
+
|
184
|
+
/* A class for differentiating between strings and blobs, when binding them
|
185
|
+
* into statements.
|
186
|
+
*/
|
187
|
+
cSqlite3Blob = rb_define_class_under(mSqlite3, "Blob", rb_cString);
|
188
|
+
|
189
|
+
/* Initialize the sqlite3 library */
|
190
|
+
#ifdef HAVE_SQLITE3_INITIALIZE
|
191
|
+
sqlite3_initialize();
|
192
|
+
#endif
|
193
|
+
|
194
|
+
init_sqlite3_constants();
|
195
|
+
init_sqlite3_database();
|
196
|
+
init_sqlite3_statement();
|
197
|
+
#ifdef HAVE_SQLITE3_BACKUP_INIT
|
198
|
+
init_sqlite3_backup();
|
199
|
+
#endif
|
200
|
+
rb_define_singleton_method(mSqlite3, "sqlcipher?", using_sqlcipher, 0);
|
201
|
+
rb_define_singleton_method(mSqlite3, "libversion", libversion, 0);
|
202
|
+
rb_define_singleton_method(mSqlite3, "threadsafe", threadsafe_p, 0);
|
203
|
+
rb_define_singleton_method(mSqlite3, "status", rb_sqlite3_status, -1);
|
204
|
+
rb_define_const(mSqlite3, "SQLITE_VERSION", rb_str_new2(SQLITE_VERSION));
|
205
|
+
rb_define_const(mSqlite3, "SQLITE_VERSION_NUMBER", INT2FIX(SQLITE_VERSION_NUMBER));
|
206
|
+
rb_define_const(mSqlite3, "SQLITE_LOADED_VERSION", rb_str_new2(sqlite3_libversion()));
|
207
|
+
|
208
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#ifndef SQLITE3_RUBY
|
2
|
+
#define SQLITE3_RUBY
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
|
6
|
+
#ifdef UNUSED
|
7
|
+
#elif defined(__GNUC__)
|
8
|
+
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
|
9
|
+
#elif defined(__LCLINT__)
|
10
|
+
# define UNUSED(x) /*@unused@*/ x
|
11
|
+
#else
|
12
|
+
# define UNUSED(x) x
|
13
|
+
#endif
|
14
|
+
|
15
|
+
#include <ruby/encoding.h>
|
16
|
+
|
17
|
+
#define USASCII_P(_obj) (rb_enc_get_index(_obj) == rb_usascii_encindex())
|
18
|
+
#define UTF8_P(_obj) (rb_enc_get_index(_obj) == rb_utf8_encindex())
|
19
|
+
#define UTF16_LE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16LE"))
|
20
|
+
#define UTF16_BE_P(_obj) (rb_enc_get_index(_obj) == rb_enc_find_index("UTF-16BE"))
|
21
|
+
#define SQLITE3_UTF8_STR_NEW2(_obj) (rb_utf8_str_new_cstr(_obj))
|
22
|
+
|
23
|
+
#ifdef USING_SQLCIPHER_INC_SUBDIR
|
24
|
+
# include <sqlcipher/sqlite3.h>
|
25
|
+
#else
|
26
|
+
# include <sqlite3.h>
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#ifndef HAVE_TYPE_SQLITE3_INT64
|
30
|
+
typedef sqlite_int64 sqlite3_int64;
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#ifndef HAVE_TYPE_SQLITE3_UINT64
|
34
|
+
typedef sqlite_uint64 sqlite3_uint64;
|
35
|
+
#endif
|
36
|
+
|
37
|
+
extern VALUE mSqlite3;
|
38
|
+
extern VALUE cSqlite3Blob;
|
39
|
+
|
40
|
+
#include <database.h>
|
41
|
+
#include <statement.h>
|
42
|
+
#include <exception.h>
|
43
|
+
#include <backup.h>
|
44
|
+
#include <timespec.h>
|
45
|
+
|
46
|
+
int bignum_to_int64(VALUE big, sqlite3_int64 *result);
|
47
|
+
|
48
|
+
#endif
|