aim-sqlite3 2.9.6.1.rc1-x86_64-linux-gnu

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.
@@ -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