aim-sqlite3 2.9.6.1.rc1
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 +1062 -0
- data/CONTRIBUTING.md +130 -0
- data/FAQ.md +399 -0
- data/INSTALLATION.md +267 -0
- data/LICENSE +23 -0
- data/README.md +218 -0
- data/dependencies.yml +13 -0
- data/ext/sqlite3/aggregator.c +314 -0
- data/ext/sqlite3/aggregator.h +14 -0
- data/ext/sqlite3/backup.c +190 -0
- data/ext/sqlite3/backup.h +15 -0
- data/ext/sqlite3/database.c +1263 -0
- data/ext/sqlite3/database.h +36 -0
- data/ext/sqlite3/exception.c +122 -0
- data/ext/sqlite3/exception.h +12 -0
- data/ext/sqlite3/extconf.rb +299 -0
- data/ext/sqlite3/gvl.c +88 -0
- data/ext/sqlite3/gvl.h +15 -0
- data/ext/sqlite3/sqlite3.c +225 -0
- data/ext/sqlite3/sqlite3_ruby.h +49 -0
- data/ext/sqlite3/statement.c +755 -0
- data/ext/sqlite3/statement.h +17 -0
- data/ext/sqlite3/timespec.h +20 -0
- data/lib/sqlite3/cli.rb +8 -0
- data/lib/sqlite3/constants.rb +198 -0
- data/lib/sqlite3/database.rb +798 -0
- data/lib/sqlite3/errors.rb +88 -0
- data/lib/sqlite3/fork_safety.rb +66 -0
- data/lib/sqlite3/pragmas.rb +648 -0
- data/lib/sqlite3/resultset.rb +96 -0
- data/lib/sqlite3/statement.rb +208 -0
- data/lib/sqlite3/value.rb +54 -0
- data/lib/sqlite3/version.rb +4 -0
- data/lib/sqlite3/version_info.rb +17 -0
- data/lib/sqlite3.rb +20 -0
- data/ports/archives/sqlite-autoconf-3530200.tar.gz +0 -0
- metadata +114 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#ifndef SQLITE3_DATABASE_RUBY
|
|
2
|
+
#define SQLITE3_DATABASE_RUBY
|
|
3
|
+
|
|
4
|
+
#include <sqlite3_ruby.h>
|
|
5
|
+
|
|
6
|
+
/* bits in the `flags` field */
|
|
7
|
+
#define SQLITE3_RB_DATABASE_READONLY 0x01
|
|
8
|
+
#define SQLITE3_RB_DATABASE_DISCARDED 0x02
|
|
9
|
+
|
|
10
|
+
struct _sqlite3Ruby {
|
|
11
|
+
sqlite3 *db;
|
|
12
|
+
VALUE busy_handler;
|
|
13
|
+
VALUE functions;
|
|
14
|
+
VALUE collations;
|
|
15
|
+
VALUE aggregators;
|
|
16
|
+
VALUE trace_handler;
|
|
17
|
+
VALUE authorizer;
|
|
18
|
+
int stmt_timeout;
|
|
19
|
+
struct timespec stmt_deadline;
|
|
20
|
+
rb_pid_t owner;
|
|
21
|
+
int flags;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
typedef struct _sqlite3Ruby sqlite3Ruby;
|
|
25
|
+
typedef sqlite3Ruby *sqlite3RubyPtr;
|
|
26
|
+
|
|
27
|
+
/* Pinning a collection doesn't pin what's in it, hence both. */
|
|
28
|
+
void rb_sqlite3_pin_array_and_contents(VALUE ary);
|
|
29
|
+
|
|
30
|
+
void init_sqlite3_database();
|
|
31
|
+
void set_sqlite3_func_result(sqlite3_context *ctx, VALUE result);
|
|
32
|
+
|
|
33
|
+
sqlite3RubyPtr sqlite3_database_unwrap(VALUE database);
|
|
34
|
+
VALUE sqlite3val2rb(sqlite3_value *val);
|
|
35
|
+
|
|
36
|
+
#endif
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#include <sqlite3_ruby.h>
|
|
2
|
+
|
|
3
|
+
static VALUE
|
|
4
|
+
status2klass(int status)
|
|
5
|
+
{
|
|
6
|
+
/* Consider only lower 8 bits, to work correctly when
|
|
7
|
+
extended result codes are enabled. */
|
|
8
|
+
switch (status & 0xff) {
|
|
9
|
+
case SQLITE_OK:
|
|
10
|
+
return Qnil;
|
|
11
|
+
case SQLITE_ERROR:
|
|
12
|
+
return rb_path2class("SQLite3::SQLException");
|
|
13
|
+
case SQLITE_INTERNAL:
|
|
14
|
+
return rb_path2class("SQLite3::InternalException");
|
|
15
|
+
case SQLITE_PERM:
|
|
16
|
+
return rb_path2class("SQLite3::PermissionException");
|
|
17
|
+
case SQLITE_ABORT:
|
|
18
|
+
return rb_path2class("SQLite3::AbortException");
|
|
19
|
+
case SQLITE_BUSY:
|
|
20
|
+
return rb_path2class("SQLite3::BusyException");
|
|
21
|
+
case SQLITE_LOCKED:
|
|
22
|
+
return rb_path2class("SQLite3::LockedException");
|
|
23
|
+
case SQLITE_NOMEM:
|
|
24
|
+
return rb_path2class("SQLite3::MemoryException");
|
|
25
|
+
case SQLITE_READONLY:
|
|
26
|
+
return rb_path2class("SQLite3::ReadOnlyException");
|
|
27
|
+
case SQLITE_INTERRUPT:
|
|
28
|
+
return rb_path2class("SQLite3::InterruptException");
|
|
29
|
+
case SQLITE_IOERR:
|
|
30
|
+
return rb_path2class("SQLite3::IOException");
|
|
31
|
+
case SQLITE_CORRUPT:
|
|
32
|
+
return rb_path2class("SQLite3::CorruptException");
|
|
33
|
+
case SQLITE_NOTFOUND:
|
|
34
|
+
return rb_path2class("SQLite3::NotFoundException");
|
|
35
|
+
case SQLITE_FULL:
|
|
36
|
+
return rb_path2class("SQLite3::FullException");
|
|
37
|
+
case SQLITE_CANTOPEN:
|
|
38
|
+
return rb_path2class("SQLite3::CantOpenException");
|
|
39
|
+
case SQLITE_PROTOCOL:
|
|
40
|
+
return rb_path2class("SQLite3::ProtocolException");
|
|
41
|
+
case SQLITE_EMPTY:
|
|
42
|
+
return rb_path2class("SQLite3::EmptyException");
|
|
43
|
+
case SQLITE_SCHEMA:
|
|
44
|
+
return rb_path2class("SQLite3::SchemaChangedException");
|
|
45
|
+
case SQLITE_TOOBIG:
|
|
46
|
+
return rb_path2class("SQLite3::TooBigException");
|
|
47
|
+
case SQLITE_CONSTRAINT:
|
|
48
|
+
return rb_path2class("SQLite3::ConstraintException");
|
|
49
|
+
case SQLITE_MISMATCH:
|
|
50
|
+
return rb_path2class("SQLite3::MismatchException");
|
|
51
|
+
case SQLITE_MISUSE:
|
|
52
|
+
return rb_path2class("SQLite3::MisuseException");
|
|
53
|
+
case SQLITE_NOLFS:
|
|
54
|
+
return rb_path2class("SQLite3::UnsupportedException");
|
|
55
|
+
case SQLITE_AUTH:
|
|
56
|
+
return rb_path2class("SQLite3::AuthorizationException");
|
|
57
|
+
case SQLITE_FORMAT:
|
|
58
|
+
return rb_path2class("SQLite3::FormatException");
|
|
59
|
+
case SQLITE_RANGE:
|
|
60
|
+
return rb_path2class("SQLite3::RangeException");
|
|
61
|
+
case SQLITE_NOTADB:
|
|
62
|
+
return rb_path2class("SQLite3::NotADatabaseException");
|
|
63
|
+
default:
|
|
64
|
+
return rb_path2class("SQLite3::Exception");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void
|
|
69
|
+
rb_sqlite3_raise(sqlite3 *db, int status)
|
|
70
|
+
{
|
|
71
|
+
VALUE klass = status2klass(status);
|
|
72
|
+
if (NIL_P(klass)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
VALUE exception = rb_exc_new2(klass, sqlite3_errmsg(db));
|
|
77
|
+
rb_iv_set(exception, "@code", INT2FIX(status));
|
|
78
|
+
|
|
79
|
+
rb_exc_raise(exception);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* accepts a sqlite3 error message as the final argument, which will be `sqlite3_free`d
|
|
84
|
+
*/
|
|
85
|
+
void
|
|
86
|
+
rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg)
|
|
87
|
+
{
|
|
88
|
+
VALUE klass = status2klass(status);
|
|
89
|
+
if (NIL_P(klass)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
VALUE exception = rb_exc_new2(klass, msg);
|
|
94
|
+
rb_iv_set(exception, "@code", INT2FIX(status));
|
|
95
|
+
sqlite3_free((void *)msg);
|
|
96
|
+
|
|
97
|
+
rb_exc_raise(exception);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
void
|
|
101
|
+
rb_sqlite3_raise_with_sql(sqlite3 *db, int status, const char *sql)
|
|
102
|
+
{
|
|
103
|
+
VALUE klass = status2klass(status);
|
|
104
|
+
if (NIL_P(klass)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const char *error_msg = sqlite3_errmsg(db);
|
|
109
|
+
int error_offset = -1;
|
|
110
|
+
#ifdef HAVE_SQLITE3_ERROR_OFFSET
|
|
111
|
+
error_offset = sqlite3_error_offset(db);
|
|
112
|
+
#endif
|
|
113
|
+
|
|
114
|
+
VALUE exception = rb_exc_new2(klass, error_msg);
|
|
115
|
+
rb_iv_set(exception, "@code", INT2FIX(status));
|
|
116
|
+
if (sql) {
|
|
117
|
+
rb_iv_set(exception, "@sql", rb_str_new2(sql));
|
|
118
|
+
rb_iv_set(exception, "@sql_offset", INT2FIX(error_offset));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
rb_exc_raise(exception);
|
|
122
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
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
|
+
#define CHECK_PREPARE(_db, _status, _sql) rb_sqlite3_raise_with_sql(_db, _status, _sql)
|
|
7
|
+
|
|
8
|
+
void rb_sqlite3_raise(sqlite3 *db, int status);
|
|
9
|
+
void rb_sqlite3_raise_msg(sqlite3 *db, int status, const char *msg);
|
|
10
|
+
void rb_sqlite3_raise_with_sql(sqlite3 *db, int status, const char *sql);
|
|
11
|
+
|
|
12
|
+
#endif
|
|
@@ -0,0 +1,299 @@
|
|
|
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
|
+
"--disable-shared",
|
|
54
|
+
"--enable-static",
|
|
55
|
+
"--enable-fts5",
|
|
56
|
+
"--disable-readline" # keeps the sqlite3 program portable
|
|
57
|
+
]
|
|
58
|
+
ENV.to_h.tap do |env|
|
|
59
|
+
user_cflags = with_config("sqlite-cflags")
|
|
60
|
+
more_cflags = [
|
|
61
|
+
"-fPIC", # needed for linking the static library into a shared library
|
|
62
|
+
"-O2", # see https://github.com/sparklemotion/sqlite3-ruby/issues/335 for some benchmarks
|
|
63
|
+
"-fvisibility=hidden", # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
|
|
64
|
+
"-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1",
|
|
65
|
+
"-DSQLITE_USE_URI=1",
|
|
66
|
+
"-DSQLITE_ENABLE_DBPAGE_VTAB=1",
|
|
67
|
+
"-DSQLITE_ENABLE_DBSTAT_VTAB=1",
|
|
68
|
+
"-DSQLITE_MAX_ATTACHED=50"
|
|
69
|
+
]
|
|
70
|
+
env["CFLAGS"] = [user_cflags, env["CFLAGS"], more_cflags].flatten.join(" ")
|
|
71
|
+
recipe.configure_options += env.slice(*ENV_ALLOWLIST)
|
|
72
|
+
.map { |key, value| "#{key}=#{value.strip}" }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
unless File.exist?(File.join(recipe.target, recipe.host, recipe.name, recipe.version))
|
|
76
|
+
recipe.cook
|
|
77
|
+
end
|
|
78
|
+
recipe.activate
|
|
79
|
+
|
|
80
|
+
# on macos, pkg-config will not return --cflags without this
|
|
81
|
+
ENV["PKG_CONFIG_ALLOW_SYSTEM_CFLAGS"] = "t"
|
|
82
|
+
|
|
83
|
+
# only needed for Ruby 3.1.3, see https://bugs.ruby-lang.org/issues/19233
|
|
84
|
+
RbConfig::CONFIG["PKG_CONFIG"] = config_string("PKG_CONFIG") || "pkg-config"
|
|
85
|
+
|
|
86
|
+
lib_path = File.join(recipe.path, "lib")
|
|
87
|
+
pcfile = File.join(lib_path, "pkgconfig", "sqlite3.pc")
|
|
88
|
+
abort_pkg_config("pkg_config") unless pkg_config(pcfile)
|
|
89
|
+
|
|
90
|
+
# see https://bugs.ruby-lang.org/issues/18490
|
|
91
|
+
ldflags = xpopen(["pkg-config", "--libs", "--static", pcfile], err: [:child, :out], &:read)
|
|
92
|
+
abort_pkg_config("xpopen") unless $?.success?
|
|
93
|
+
ldflags = ldflags.split
|
|
94
|
+
|
|
95
|
+
# see https://github.com/flavorjones/mini_portile/issues/118
|
|
96
|
+
"-L#{lib_path}".tap do |lib_path_flag|
|
|
97
|
+
ldflags.prepend(lib_path_flag) unless ldflags.include?(lib_path_flag)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
ldflags.each { |ldflag| append_ldflags(ldflag) }
|
|
101
|
+
|
|
102
|
+
append_cppflags("-DUSING_PACKAGED_LIBRARIES")
|
|
103
|
+
append_cppflags("-DUSING_PRECOMPILED_LIBRARIES") if cross_build?
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def configure_extension
|
|
108
|
+
append_cflags("-fvisibility=hidden") # see https://github.com/rake-compiler/rake-compiler-dock/issues/87
|
|
109
|
+
|
|
110
|
+
if sqlcipher? && find_header("sqlcipher/sqlite3.h")
|
|
111
|
+
append_cppflags("-DUSING_SQLCIPHER_INC_SUBDIR")
|
|
112
|
+
elsif find_header("sqlite3.h")
|
|
113
|
+
# noop
|
|
114
|
+
else
|
|
115
|
+
abort_could_not_find("sqlite3.h")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
abort_could_not_find(libname) unless find_library(libname, "sqlite3_libversion_number", "sqlite3.h")
|
|
119
|
+
|
|
120
|
+
# Truffle Ruby doesn't support this yet:
|
|
121
|
+
# https://github.com/oracle/truffleruby/issues/3408
|
|
122
|
+
have_func("rb_enc_interned_str_cstr")
|
|
123
|
+
|
|
124
|
+
# Functions defined in 1.9 but not 1.8
|
|
125
|
+
have_func("rb_proc_arity")
|
|
126
|
+
|
|
127
|
+
# Functions defined in 2.1 but not 2.0
|
|
128
|
+
have_func("rb_integer_pack")
|
|
129
|
+
|
|
130
|
+
# These functions may not be defined
|
|
131
|
+
have_func("sqlite3_initialize")
|
|
132
|
+
have_func("sqlite3_backup_init")
|
|
133
|
+
have_func("sqlite3_column_database_name")
|
|
134
|
+
have_func("sqlite3_enable_load_extension")
|
|
135
|
+
have_func("sqlite3_load_extension")
|
|
136
|
+
|
|
137
|
+
unless have_func("sqlite3_open_v2") # https://www.sqlite.org/releaselog/3_5_0.html
|
|
138
|
+
abort("\nPlease use a version of SQLite3 >= 3.5.0\n\n")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
have_func("sqlite3_prepare_v2")
|
|
142
|
+
have_func("sqlite3_db_name", "sqlite3.h") # v3.39.0
|
|
143
|
+
have_func("sqlite3_error_offset", "sqlite3.h") # v3.38.0
|
|
144
|
+
|
|
145
|
+
have_type("sqlite3_int64", "sqlite3.h")
|
|
146
|
+
have_type("sqlite3_uint64", "sqlite3.h")
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def minimal_recipe
|
|
150
|
+
require "mini_portile2"
|
|
151
|
+
|
|
152
|
+
MiniPortile.new(libname, sqlite3_config[:version]).tap do |recipe|
|
|
153
|
+
if sqlite_source_dir
|
|
154
|
+
recipe.source_directory = sqlite_source_dir
|
|
155
|
+
else
|
|
156
|
+
recipe.files = sqlite3_config[:files]
|
|
157
|
+
recipe.target = File.join(package_root_dir, "ports")
|
|
158
|
+
recipe.patch_files = Dir[File.join(package_root_dir, "patches", "*.patch")].sort
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def package_root_dir
|
|
164
|
+
File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def sqlite3_config
|
|
168
|
+
mini_portile_config[:sqlite3]
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def mini_portile_config
|
|
172
|
+
YAML.load_file(File.join(package_root_dir, "dependencies.yml"), symbolize_names: true)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def abort_could_not_find(missing)
|
|
176
|
+
abort("\nCould not find #{missing}.\nPlease visit https://github.com/sparklemotion/sqlite3-ruby for installation instructions.\n\n")
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def abort_pkg_config(id)
|
|
180
|
+
abort("\nCould not configure the build properly (#{id}). Please install the `pkg-config` utility.\n\n")
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def cross_build?
|
|
184
|
+
enable_config("cross-build")
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def sqlite_source_dir
|
|
188
|
+
arg_config("--with-sqlite-source-dir")
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def download
|
|
192
|
+
minimal_recipe.download
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def darwin?
|
|
196
|
+
RbConfig::CONFIG["target_os"].include?("darwin")
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def windows?
|
|
200
|
+
RbConfig::CONFIG["target_os"].match?(/mingw|mswin/)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def print_help
|
|
204
|
+
print(<<~TEXT)
|
|
205
|
+
USAGE: ruby #{$PROGRAM_NAME} [options]
|
|
206
|
+
|
|
207
|
+
Flags that are always valid:
|
|
208
|
+
|
|
209
|
+
--disable-system-libraries
|
|
210
|
+
Use the packaged libraries, and ignore the system libraries.
|
|
211
|
+
(This is the default behavior.)
|
|
212
|
+
|
|
213
|
+
--enable-system-libraries
|
|
214
|
+
Use system libraries instead of building and using the packaged libraries.
|
|
215
|
+
|
|
216
|
+
--with-sqlcipher
|
|
217
|
+
Use libsqlcipher instead of libsqlite3.
|
|
218
|
+
(Implies `--enable-system-libraries`.)
|
|
219
|
+
|
|
220
|
+
--with-sqlite-source-dir=DIRECTORY
|
|
221
|
+
(dev only) Build sqlite from the source code in DIRECTORY
|
|
222
|
+
|
|
223
|
+
--help
|
|
224
|
+
Display this message.
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
Flags only used when using system libraries:
|
|
228
|
+
|
|
229
|
+
General (applying to all system libraries):
|
|
230
|
+
|
|
231
|
+
--with-opt-dir=DIRECTORY
|
|
232
|
+
Look for headers and libraries in DIRECTORY.
|
|
233
|
+
|
|
234
|
+
--with-opt-lib=DIRECTORY
|
|
235
|
+
Look for libraries in DIRECTORY.
|
|
236
|
+
|
|
237
|
+
--with-opt-include=DIRECTORY
|
|
238
|
+
Look for headers in DIRECTORY.
|
|
239
|
+
|
|
240
|
+
Related to sqlcipher:
|
|
241
|
+
|
|
242
|
+
--with-sqlcipher-dir=DIRECTORY
|
|
243
|
+
Look for sqlcipher headers and library in DIRECTORY.
|
|
244
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
|
245
|
+
|
|
246
|
+
--with-sqlcipher-lib=DIRECTORY
|
|
247
|
+
Look for sqlcipher library in DIRECTORY.
|
|
248
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
|
249
|
+
|
|
250
|
+
--with-sqlcipher-include=DIRECTORY
|
|
251
|
+
Look for sqlcipher headers in DIRECTORY.
|
|
252
|
+
(Implies `--with-sqlcipher` and `--enable-system-libraries`.)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
Flags only used when building and using the packaged libraries:
|
|
256
|
+
|
|
257
|
+
--with-sqlite-cflags=CFLAGS
|
|
258
|
+
Explicitly pass compiler flags to the sqlite library build. These flags will
|
|
259
|
+
appear on the commandline before any flags set in the CFLAGS environment
|
|
260
|
+
variable. This is useful for setting compilation options in your project's
|
|
261
|
+
bundler config. See INSTALLATION.md for more information.
|
|
262
|
+
|
|
263
|
+
--enable-cross-build
|
|
264
|
+
Enable cross-build mode. (You probably do not want to set this manually.)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
Environment variables used for compiling the gem's C extension:
|
|
268
|
+
|
|
269
|
+
CC
|
|
270
|
+
Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
Environment variables passed through to the compilation of sqlite:
|
|
274
|
+
|
|
275
|
+
CC
|
|
276
|
+
CPPFLAGS
|
|
277
|
+
CFLAGS
|
|
278
|
+
LDFLAGS
|
|
279
|
+
LIBS
|
|
280
|
+
LT_SYS_LIBRARY_PATH
|
|
281
|
+
CPP
|
|
282
|
+
|
|
283
|
+
TEXT
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
if arg_config("--help")
|
|
290
|
+
Sqlite3::ExtConf.print_help
|
|
291
|
+
exit!(0)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
if arg_config("--download-dependencies")
|
|
295
|
+
Sqlite3::ExtConf.download
|
|
296
|
+
exit!(0)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
Sqlite3::ExtConf.configure
|
data/ext/sqlite3/gvl.c
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#include <sqlite3_ruby.h>
|
|
2
|
+
#include <ruby/thread.h>
|
|
3
|
+
|
|
4
|
+
#if defined(_MSC_VER)
|
|
5
|
+
# define SQLITE3_TLS __declspec(thread)
|
|
6
|
+
#else
|
|
7
|
+
# define SQLITE3_TLS __thread
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
/* Per OS thread: set while this thread is inside a without_gvl sqlite call. */
|
|
11
|
+
static SQLITE3_TLS int in_nogvl = 0;
|
|
12
|
+
|
|
13
|
+
/* Unblocking function: Thread#kill / Thread#raise call this from another
|
|
14
|
+
* thread; sqlite3_interrupt is thread-safe and makes the running call return
|
|
15
|
+
* SQLITE_INTERRUPT. */
|
|
16
|
+
static void
|
|
17
|
+
interrupt_db(void *db)
|
|
18
|
+
{
|
|
19
|
+
sqlite3_interrupt((sqlite3 *)db);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static void *
|
|
23
|
+
step_body(void *stmt)
|
|
24
|
+
{
|
|
25
|
+
return (void *)(intptr_t)sqlite3_step((sqlite3_stmt *)stmt);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
int
|
|
29
|
+
rb_sqlite3_step_without_gvl(sqlite3_stmt *stmt)
|
|
30
|
+
{
|
|
31
|
+
int was_nogvl = in_nogvl;
|
|
32
|
+
int status;
|
|
33
|
+
|
|
34
|
+
in_nogvl = 1;
|
|
35
|
+
status = (int)(intptr_t)rb_thread_call_without_gvl(
|
|
36
|
+
step_body, stmt, interrupt_db, sqlite3_db_handle(stmt));
|
|
37
|
+
|
|
38
|
+
in_nogvl = was_nogvl;
|
|
39
|
+
|
|
40
|
+
return status;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
typedef struct {
|
|
44
|
+
sqlite3 *db;
|
|
45
|
+
const char *sql;
|
|
46
|
+
sqlite3_callback callback;
|
|
47
|
+
void *callback_arg;
|
|
48
|
+
char **errmsg;
|
|
49
|
+
} exec_args_t;
|
|
50
|
+
|
|
51
|
+
static void *
|
|
52
|
+
exec_body(void *ptr)
|
|
53
|
+
{
|
|
54
|
+
exec_args_t *args = (exec_args_t *)ptr;
|
|
55
|
+
return (void *)(intptr_t)sqlite3_exec(
|
|
56
|
+
args->db, args->sql, args->callback, args->callback_arg, args->errmsg);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
int
|
|
60
|
+
rb_sqlite3_exec_without_gvl(sqlite3 *db, const char *sql, sqlite3_callback callback,
|
|
61
|
+
void *callback_arg, char **errmsg)
|
|
62
|
+
{
|
|
63
|
+
exec_args_t args = { db, sql, callback, callback_arg, errmsg };
|
|
64
|
+
int was_nogvl = in_nogvl;
|
|
65
|
+
int status;
|
|
66
|
+
|
|
67
|
+
in_nogvl = 1;
|
|
68
|
+
status = (int)(intptr_t)rb_thread_call_without_gvl(exec_body, &args, interrupt_db, db);
|
|
69
|
+
in_nogvl = was_nogvl;
|
|
70
|
+
|
|
71
|
+
return status;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Callbacks also fire from sqlite calls made with the GVL held (prepare,
|
|
75
|
+
* close), and taking the GVL twice is a fatal error. */
|
|
76
|
+
void *
|
|
77
|
+
rb_sqlite3_with_gvl(void *(*func)(void *), void *data)
|
|
78
|
+
{
|
|
79
|
+
void *result;
|
|
80
|
+
|
|
81
|
+
if (!in_nogvl) { return func(data); }
|
|
82
|
+
|
|
83
|
+
in_nogvl = 0;
|
|
84
|
+
result = rb_thread_call_with_gvl(func, data);
|
|
85
|
+
in_nogvl = 1;
|
|
86
|
+
|
|
87
|
+
return result;
|
|
88
|
+
}
|
data/ext/sqlite3/gvl.h
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#ifndef SQLITE3_GVL_RUBY
|
|
2
|
+
#define SQLITE3_GVL_RUBY
|
|
3
|
+
|
|
4
|
+
#include <sqlite3_ruby.h>
|
|
5
|
+
|
|
6
|
+
/* sqlite3_step and sqlite3_exec run without the GVL so other threads keep
|
|
7
|
+
* running, and so Thread#kill / Thread#raise can cancel them through
|
|
8
|
+
* sqlite3_interrupt. sqlite calls Ruby callbacks on the same thread, so each
|
|
9
|
+
* callback goes through rb_sqlite3_with_gvl to take the GVL back first. */
|
|
10
|
+
int rb_sqlite3_step_without_gvl(sqlite3_stmt *stmt);
|
|
11
|
+
int rb_sqlite3_exec_without_gvl(sqlite3 *db, const char *sql, sqlite3_callback callback,
|
|
12
|
+
void *callback_arg, char **errmsg);
|
|
13
|
+
void *rb_sqlite3_with_gvl(void *(*func)(void *), void *data);
|
|
14
|
+
|
|
15
|
+
#endif
|