sqlite3 2.9.6-x86_64-linux-gnu → 2.10.0-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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -1
- data/dependencies.yml +8 -8
- data/ext/sqlite3/database.c +147 -2
- data/ext/sqlite3/extconf.rb +8 -2
- data/ext/sqlite3/statement.c +69 -3
- data/ext/sqlite3/timespec.h +9 -0
- data/lib/sqlite3/3.2/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.3/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.4/sqlite3_native.so +0 -0
- data/lib/sqlite3/4.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/resultset.rb +10 -4
- data/lib/sqlite3/statement.rb +29 -10
- data/lib/sqlite3/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 925936bfaad5493f668bfa519612ad3253bde99a26f3348a4a43f3d06898590a
|
|
4
|
+
data.tar.gz: 3c1af19b4c916d77fcbf1814cf129720ddba94df13f700ae5b3c150a5b3f8a0b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be09b9ecca49b6be1546b6f7fcef1f11a9937e5d88dfe0c42479bae8cb37f73dd6e55d0cd775290965e86a9f0948bb808c1841152a2622ac0c09c6e745a91a6f
|
|
7
|
+
data.tar.gz: 3ab7d2078c7b13596e4c6837d8798fe88e41cab4eeda9d85d9093467612b6cf10ec97432c5b2a8afeb5b6250903ebb71a632a3e6c9f7f5623a3d37d564131049
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# sqlite3-ruby Changelog
|
|
2
2
|
|
|
3
|
+
## 2.10.0 / 2026-10-13
|
|
4
|
+
|
|
5
|
+
### Dependencies
|
|
6
|
+
|
|
7
|
+
- Vendored sqlite is updated to [v3.54.0](https://www.sqlite.org/releaselog/3_54_0.html) (from v3.53.2). #750 @flavorjones
|
|
8
|
+
|
|
9
|
+
Notable changes in this version include:
|
|
10
|
+
- `ALTER TABLE` now raises an error when adding, renaming, or dropping a column named `ROWID`, `_ROWID_`, or `OID`.
|
|
11
|
+
- The authorizer callback is now invoked for SQL functions in the `DEFAULT` clauses of `CREATE TABLE` statements.
|
|
12
|
+
- SQLite no longer supports Windows XP or earlier. On Windows, the precompiled gem and any installation that compiles the vendored sqlite now require Windows Vista or later.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `ResultSet#each` and `#each_hash` return an `Enumerator` when called without a block. Previously they raised `LocalJumpError`. #656 @kch
|
|
17
|
+
- Introduce `Database#serialize`, which returns a database as a binary string, and `Database#deserialize`, which replaces a database with the contents of such a string. These wrap [`sqlite3_serialize()`](https://www.sqlite.org/c3ref/serialize.html) and [`sqlite3_deserialize()`](https://www.sqlite.org/c3ref/deserialize.html). Both methods are defined only when SQLite was compiled without `SQLITE_OMIT_DESERIALIZE`, and `Database#deserialize` also requires that the loaded SQLite is v3.54.0 or later. An image of a database in WAL mode cannot be queried after deserializing; see the `Database#deserialize` documentation. #685 @Maaarcocr
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Fix `Database#statement_timeout=` interrupting statements almost immediately instead of after the timeout elapsed, including re-executed prepared statements and calls to `Database#execute_batch2`. #737 @palkan @flavorjones
|
|
22
|
+
|
|
23
|
+
### Improved
|
|
24
|
+
|
|
25
|
+
- On CRuby, `Statement#types` allocates fewer strings. Each declared type is downcased and interned in C, instead of allocating two strings per column. #743 @jhawthorn
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- `ResultSet#each` and `#each_hash` return the result set when called with a block. As a consequence, `Database#execute` and `#execute2` called with a block return the closed `ResultSet` instead of `nil`. #656 @kch
|
|
30
|
+
- `Statement#columns` and `Statement#types` return frozen arrays, and the strings in `Statement#types` are frozen. Code that mutates them now raises `FrozenError`. #743 @jhawthorn
|
|
31
|
+
- `Statement#column_decltype` and `Statement#types` return UTF-8 strings. Previously they returned ASCII-8BIT strings. #743 @jhawthorn
|
|
32
|
+
|
|
33
|
+
|
|
3
34
|
## 2.9.6 / 2026-08-11
|
|
4
35
|
|
|
5
36
|
### Security / Stability
|
|
@@ -25,7 +56,7 @@
|
|
|
25
56
|
|
|
26
57
|
### Dependencies
|
|
27
58
|
|
|
28
|
-
- Vendored sqlite is updated to [v3.53.2](https://www.sqlite.org/releaselog/
|
|
59
|
+
- Vendored sqlite is updated to [v3.53.2](https://www.sqlite.org/releaselog/3_53_2.html) (from v3.53.1). #709 @flavorjones
|
|
29
60
|
|
|
30
61
|
### Security / Stability
|
|
31
62
|
|
data/dependencies.yml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
sqlite3:
|
|
2
2
|
# checksum verified by first checking the published sha3(256) checksum against https://sqlite.org/download.html:
|
|
3
|
-
#
|
|
3
|
+
# f5e3e724e9c9b3b5d512c76b02082091a59eeea9becd169a9fbf4d376403acce
|
|
4
4
|
#
|
|
5
|
-
# $ sha3sum -a 256 ports/archives/sqlite-autoconf-
|
|
6
|
-
#
|
|
5
|
+
# $ sha3sum -a 256 ports/archives/sqlite-autoconf-3540000.tar.gz
|
|
6
|
+
# f5e3e724e9c9b3b5d512c76b02082091a59eeea9becd169a9fbf4d376403acce ports/archives/sqlite-autoconf-3540000.tar.gz
|
|
7
7
|
#
|
|
8
|
-
# $ sha256sum ports/archives/sqlite-autoconf-
|
|
9
|
-
#
|
|
10
|
-
version: "3.
|
|
8
|
+
# $ sha256sum ports/archives/sqlite-autoconf-3540000.tar.gz
|
|
9
|
+
# 134ec0802dda5795816e25d25872d20b312cb3973438c49b30bc40b7705ea9ed ports/archives/sqlite-autoconf-3540000.tar.gz
|
|
10
|
+
version: "3.54.0"
|
|
11
11
|
files:
|
|
12
|
-
- url: "https://sqlite.org/2026/sqlite-autoconf-
|
|
13
|
-
sha256: "
|
|
12
|
+
- url: "https://sqlite.org/2026/sqlite-autoconf-3540000.tar.gz"
|
|
13
|
+
sha256: "134ec0802dda5795816e25d25872d20b312cb3973438c49b30bc40b7705ea9ed"
|
data/ext/sqlite3/database.c
CHANGED
|
@@ -417,8 +417,10 @@ rb_sqlite3_statement_timeout(void *context)
|
|
|
417
417
|
clock_gettime(CLOCK_MONOTONIC, ¤tTime);
|
|
418
418
|
|
|
419
419
|
if (!timespecisset(&ctx->stmt_deadline)) {
|
|
420
|
-
|
|
421
|
-
ctx->
|
|
420
|
+
struct timespec timeout;
|
|
421
|
+
timeout.tv_sec = ctx->stmt_timeout / 1000;
|
|
422
|
+
timeout.tv_nsec = (ctx->stmt_timeout % 1000) * 1000000L;
|
|
423
|
+
timespecadd(¤tTime, &timeout, &ctx->stmt_deadline);
|
|
422
424
|
} else if (timespecafter(¤tTime, &ctx->stmt_deadline)) {
|
|
423
425
|
return 1;
|
|
424
426
|
}
|
|
@@ -990,6 +992,8 @@ exec_batch(VALUE self, VALUE sql, VALUE results_as_hash)
|
|
|
990
992
|
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
|
991
993
|
REQUIRE_OPEN_DB(ctx);
|
|
992
994
|
|
|
995
|
+
timespecclear(&ctx->stmt_deadline);
|
|
996
|
+
|
|
993
997
|
if (results_as_hash == Qtrue) {
|
|
994
998
|
status = sqlite3_exec(ctx->db, StringValuePtr(sql), (sqlite3_callback)hash_callback_function,
|
|
995
999
|
(void *)callback_ary,
|
|
@@ -1024,6 +1028,137 @@ db_filename(VALUE self, VALUE db_name)
|
|
|
1024
1028
|
return Qnil;
|
|
1025
1029
|
}
|
|
1026
1030
|
|
|
1031
|
+
#ifdef HAVE_SQLITE3_SERIALIZE
|
|
1032
|
+
/* call-seq: db.serialize(database_name = "main")
|
|
1033
|
+
*
|
|
1034
|
+
* Serialize the database into a binary string.
|
|
1035
|
+
*
|
|
1036
|
+
* [database_name] The name of the database to serialize. The default value
|
|
1037
|
+
* is +main+ which is the main database file. For ATTACHed
|
|
1038
|
+
* databases, use the name given in the ATTACH statement.
|
|
1039
|
+
*
|
|
1040
|
+
* Returns the contents of the database as a binary string. For an ordinary
|
|
1041
|
+
* on-disk database file, this is just a copy of the disk file. For an
|
|
1042
|
+
* in-memory database or a "TEMP" database, this is the same sequence of bytes
|
|
1043
|
+
* which would be written to disk if that database were backed up to disk.
|
|
1044
|
+
*
|
|
1045
|
+
* Note: This method will only be defined if SQLite was compiled without
|
|
1046
|
+
* +SQLITE_OMIT_DESERIALIZE+.
|
|
1047
|
+
*
|
|
1048
|
+
* See also: https://www.sqlite.org/c3ref/serialize.html
|
|
1049
|
+
*/
|
|
1050
|
+
static VALUE
|
|
1051
|
+
serialize(int argc, VALUE *argv, VALUE self)
|
|
1052
|
+
{
|
|
1053
|
+
sqlite3RubyPtr ctx;
|
|
1054
|
+
VALUE db_name;
|
|
1055
|
+
const char *zSchema;
|
|
1056
|
+
sqlite3_int64 size;
|
|
1057
|
+
unsigned char *data;
|
|
1058
|
+
VALUE result;
|
|
1059
|
+
|
|
1060
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
|
1061
|
+
REQUIRE_OPEN_DB(ctx);
|
|
1062
|
+
|
|
1063
|
+
rb_scan_args(argc, argv, "01", &db_name);
|
|
1064
|
+
|
|
1065
|
+
zSchema = NIL_P(db_name) ? NULL : StringValueCStr(db_name);
|
|
1066
|
+
|
|
1067
|
+
data = sqlite3_serialize(ctx->db, zSchema, &size, 0);
|
|
1068
|
+
|
|
1069
|
+
if (data == NULL && size < 0) {
|
|
1070
|
+
rb_raise(rb_path2class("SQLite3::Exception"), "unable to serialize database \"%s\"",
|
|
1071
|
+
zSchema ? zSchema : "main");
|
|
1072
|
+
}
|
|
1073
|
+
if (data == NULL && size > 0) {
|
|
1074
|
+
rb_raise(rb_eNoMemError, "failed to allocate %lld bytes for serialization", (long long)size);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
result = rb_str_new((const char *)data, (long)size);
|
|
1078
|
+
sqlite3_free(data);
|
|
1079
|
+
|
|
1080
|
+
return result;
|
|
1081
|
+
}
|
|
1082
|
+
#endif
|
|
1083
|
+
|
|
1084
|
+
#ifdef HAVE_SQLITE3_DESERIALIZE
|
|
1085
|
+
/* call-seq: db.deserialize(data, database_name = "main")
|
|
1086
|
+
*
|
|
1087
|
+
* Deserialize a binary string into the database. The database is replaced with
|
|
1088
|
+
* the contents of the serialized data.
|
|
1089
|
+
*
|
|
1090
|
+
* [data] A binary string containing the serialized database content.
|
|
1091
|
+
* This is typically obtained from a prior call to #serialize.
|
|
1092
|
+
*
|
|
1093
|
+
* [database_name] The name of the database to replace. The default value is
|
|
1094
|
+
* +main+ which is the main database file. For ATTACHed
|
|
1095
|
+
* databases, use the name given in the ATTACH statement.
|
|
1096
|
+
*
|
|
1097
|
+
* Raises SQLite3::BusyException if the database has an open read or write
|
|
1098
|
+
* transaction, including one held by an unfinished statement, or is involved in
|
|
1099
|
+
* a backup.
|
|
1100
|
+
*
|
|
1101
|
+
* Deserializing into a database backed by a file detaches the connection from
|
|
1102
|
+
* that file. The file is left unchanged, and #filename(database_name) returns an
|
|
1103
|
+
* empty string afterwards.
|
|
1104
|
+
*
|
|
1105
|
+
* ⚠ An image of a database in WAL mode deserializes without error, but later
|
|
1106
|
+
* statements, even <tt>SELECT 1</tt>, raise SQLite3::CantOpenException. Rails
|
|
1107
|
+
* enables WAL mode by default.
|
|
1108
|
+
*
|
|
1109
|
+
* ⚠ Deserializing untrusted data carries the same risks as opening an untrusted
|
|
1110
|
+
* database file. See https://www.sqlite.org/security.html
|
|
1111
|
+
*
|
|
1112
|
+
* Note: This method will only be defined if the loaded SQLite is version 3.54.0
|
|
1113
|
+
* or later and was compiled without +SQLITE_OMIT_DESERIALIZE+. Older versions do
|
|
1114
|
+
* not raise SQLite3::BusyException; they free memory that an unfinished statement
|
|
1115
|
+
* still uses.
|
|
1116
|
+
*
|
|
1117
|
+
* See also: https://www.sqlite.org/c3ref/deserialize.html
|
|
1118
|
+
*/
|
|
1119
|
+
static VALUE
|
|
1120
|
+
deserialize(int argc, VALUE *argv, VALUE self)
|
|
1121
|
+
{
|
|
1122
|
+
sqlite3RubyPtr ctx;
|
|
1123
|
+
VALUE data, db_name;
|
|
1124
|
+
const char *zSchema;
|
|
1125
|
+
unsigned char *pData;
|
|
1126
|
+
sqlite3_int64 szDb, szBuf;
|
|
1127
|
+
int status;
|
|
1128
|
+
|
|
1129
|
+
TypedData_Get_Struct(self, sqlite3Ruby, &database_type, ctx);
|
|
1130
|
+
REQUIRE_OPEN_DB(ctx);
|
|
1131
|
+
|
|
1132
|
+
rb_scan_args(argc, argv, "11", &data, &db_name);
|
|
1133
|
+
|
|
1134
|
+
StringValue(data);
|
|
1135
|
+
zSchema = NIL_P(db_name) ? NULL : StringValueCStr(db_name);
|
|
1136
|
+
szDb = RSTRING_LEN(data);
|
|
1137
|
+
|
|
1138
|
+
/* SQLite's docs advise padding the buffer with about 20 extra bytes, because a maliciously
|
|
1139
|
+
* malformed image may make SQLite read past its end. See https://www.sqlite.org/c3ref/deserialize.html
|
|
1140
|
+
*
|
|
1141
|
+
* With SQLITE_DESERIALIZE_RESIZEABLE set, SQLite copies pages out of the buffer with bounds
|
|
1142
|
+
* checks instead of reading it in place, so the padding is defensive. It also keeps the
|
|
1143
|
+
* allocation nonzero for an empty string, for which sqlite3_malloc64(0) returns NULL.
|
|
1144
|
+
*/
|
|
1145
|
+
szBuf = szDb + 20;
|
|
1146
|
+
pData = sqlite3_malloc64(szBuf);
|
|
1147
|
+
if (pData == NULL) {
|
|
1148
|
+
rb_raise(rb_eNoMemError, "failed to allocate %lld bytes for deserialization", (long long)szBuf);
|
|
1149
|
+
}
|
|
1150
|
+
memcpy(pData, RSTRING_PTR(data), (size_t)szDb);
|
|
1151
|
+
memset(pData + szDb, 0, (size_t)(szBuf - szDb));
|
|
1152
|
+
|
|
1153
|
+
status = sqlite3_deserialize(ctx->db, zSchema, pData, szDb, szDb,
|
|
1154
|
+
SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE);
|
|
1155
|
+
|
|
1156
|
+
CHECK(ctx->db, status);
|
|
1157
|
+
|
|
1158
|
+
return self;
|
|
1159
|
+
}
|
|
1160
|
+
#endif
|
|
1161
|
+
|
|
1027
1162
|
static VALUE
|
|
1028
1163
|
rb_sqlite3_open16(VALUE self, VALUE file)
|
|
1029
1164
|
{
|
|
@@ -1104,6 +1239,16 @@ init_sqlite3_database(void)
|
|
|
1104
1239
|
#endif
|
|
1105
1240
|
#endif
|
|
1106
1241
|
|
|
1242
|
+
#ifdef HAVE_SQLITE3_SERIALIZE
|
|
1243
|
+
rb_define_method(cSqlite3Database, "serialize", serialize, -1);
|
|
1244
|
+
#endif
|
|
1245
|
+
|
|
1246
|
+
#ifdef HAVE_SQLITE3_DESERIALIZE
|
|
1247
|
+
/* Before 3.54.0, sqlite3_deserialize frees memory that an unfinished statement still uses. */
|
|
1248
|
+
if (sqlite3_libversion_number() >= 3054000) {
|
|
1249
|
+
rb_define_method(cSqlite3Database, "deserialize", deserialize, -1);
|
|
1250
|
+
}
|
|
1251
|
+
#endif
|
|
1107
1252
|
|
|
1108
1253
|
rb_sqlite3_aggregator_init();
|
|
1109
1254
|
}
|
data/ext/sqlite3/extconf.rb
CHANGED
|
@@ -65,7 +65,10 @@ module Sqlite3
|
|
|
65
65
|
"-DSQLITE_ENABLE_DBPAGE_VTAB=1",
|
|
66
66
|
"-DSQLITE_ENABLE_DBSTAT_VTAB=1"
|
|
67
67
|
]
|
|
68
|
-
|
|
68
|
+
# sqlite >= 3.54 requires Vista APIs, same as ruby's default target. Placed first so a
|
|
69
|
+
# user-defined _WIN32_WINNT takes precedence.
|
|
70
|
+
windows_cflags = windows? ? ["-D_WIN32_WINNT=0x0600"] : []
|
|
71
|
+
env["CFLAGS"] = [windows_cflags, user_cflags, env["CFLAGS"], more_cflags].flatten.join(" ")
|
|
69
72
|
recipe.configure_options += env.slice(*ENV_ALLOWLIST)
|
|
70
73
|
.map { |key, value| "#{key}=#{value.strip}" }
|
|
71
74
|
end
|
|
@@ -115,9 +118,10 @@ module Sqlite3
|
|
|
115
118
|
|
|
116
119
|
abort_could_not_find(libname) unless find_library(libname, "sqlite3_libversion_number", "sqlite3.h")
|
|
117
120
|
|
|
118
|
-
#
|
|
121
|
+
# Ruby 3.0+, but not on every implementation:
|
|
119
122
|
# https://github.com/oracle/truffleruby/issues/3408
|
|
120
123
|
have_func("rb_enc_interned_str_cstr")
|
|
124
|
+
have_func("rb_enc_interned_str")
|
|
121
125
|
|
|
122
126
|
# Functions defined in 1.9 but not 1.8
|
|
123
127
|
have_func("rb_proc_arity")
|
|
@@ -139,6 +143,8 @@ module Sqlite3
|
|
|
139
143
|
have_func("sqlite3_prepare_v2")
|
|
140
144
|
have_func("sqlite3_db_name", "sqlite3.h") # v3.39.0
|
|
141
145
|
have_func("sqlite3_error_offset", "sqlite3.h") # v3.38.0
|
|
146
|
+
have_func("sqlite3_serialize", "sqlite3.h") # v3.23.0
|
|
147
|
+
have_func("sqlite3_deserialize", "sqlite3.h") # v3.23.0
|
|
142
148
|
|
|
143
149
|
have_type("sqlite3_int64", "sqlite3.h")
|
|
144
150
|
have_type("sqlite3_uint64", "sqlite3.h")
|
data/ext/sqlite3/statement.c
CHANGED
|
@@ -66,6 +66,8 @@ prepare(VALUE self, VALUE db, VALUE sql)
|
|
|
66
66
|
* variable will keep it from being GCed. */
|
|
67
67
|
ctx->db = db_ctx;
|
|
68
68
|
|
|
69
|
+
timespecclear(&db_ctx->stmt_deadline);
|
|
70
|
+
|
|
69
71
|
#ifdef HAVE_SQLITE3_PREPARE_V2
|
|
70
72
|
status = sqlite3_prepare_v2(
|
|
71
73
|
#else
|
|
@@ -79,7 +81,6 @@ prepare(VALUE self, VALUE db, VALUE sql)
|
|
|
79
81
|
);
|
|
80
82
|
|
|
81
83
|
CHECK_PREPARE(db_ctx->db, status, StringValuePtr(sql));
|
|
82
|
-
timespecclear(&db_ctx->stmt_deadline);
|
|
83
84
|
|
|
84
85
|
return rb_utf8_str_new_cstr(tail);
|
|
85
86
|
}
|
|
@@ -139,6 +140,10 @@ step(VALUE self)
|
|
|
139
140
|
|
|
140
141
|
stmt = ctx->st;
|
|
141
142
|
|
|
143
|
+
if (!sqlite3_stmt_busy(stmt)) {
|
|
144
|
+
timespecclear(&ctx->db->stmt_deadline);
|
|
145
|
+
}
|
|
146
|
+
|
|
142
147
|
value = sqlite3_step(stmt);
|
|
143
148
|
if (rb_errinfo() != Qnil) {
|
|
144
149
|
/* some user defined function was invoked as a callback during step and
|
|
@@ -216,6 +221,21 @@ step(VALUE self)
|
|
|
216
221
|
* Fixnum, it is treated as an index for a positional placeholder.
|
|
217
222
|
* Otherwise it is used as the name of the placeholder to bind to.
|
|
218
223
|
*
|
|
224
|
+
* Type mapping from Ruby to SQLite3:
|
|
225
|
+
* - +nil+ → NULL
|
|
226
|
+
* - Integer → INTEGER (or REAL when outside the signed int64 range)
|
|
227
|
+
* - Float → REAL
|
|
228
|
+
* - SQLite3::Blob → BLOB
|
|
229
|
+
* - String with Encoding::ASCII_8BIT (a.k.a. BINARY) → BLOB
|
|
230
|
+
* - String with Encoding::UTF_16LE or Encoding::UTF_16BE → TEXT (bound as UTF-16)
|
|
231
|
+
* - String (all other encodings) → TEXT (re-encoded to UTF-8 if necessary)
|
|
232
|
+
* - Any other type → raises RuntimeError
|
|
233
|
+
*
|
|
234
|
+
* Note: if you have a string with only ASCII characters but ASCII-8BIT
|
|
235
|
+
* encoding and want it bound as TEXT rather than BLOB, re-encode it first:
|
|
236
|
+
*
|
|
237
|
+
* stmt.bind_param(1, my_binary_str.encode(Encoding::UTF_8))
|
|
238
|
+
*
|
|
219
239
|
* See also #bind_params.
|
|
220
240
|
*/
|
|
221
241
|
static VALUE
|
|
@@ -398,6 +418,33 @@ interned_utf8_cstr(const char *str)
|
|
|
398
418
|
}
|
|
399
419
|
#endif
|
|
400
420
|
|
|
421
|
+
/* Like interned_utf8_cstr, but ASCII-downcases as it copies. */
|
|
422
|
+
static VALUE
|
|
423
|
+
interned_downcased_utf8_cstr(const char *str)
|
|
424
|
+
{
|
|
425
|
+
#if HAVE_RB_ENC_INTERNED_STR
|
|
426
|
+
VALUE tmp, ret;
|
|
427
|
+
char *buf;
|
|
428
|
+
size_t i, len;
|
|
429
|
+
|
|
430
|
+
len = strlen(str);
|
|
431
|
+
buf = ALLOCV_N(char, tmp, len);
|
|
432
|
+
|
|
433
|
+
for (i = 0; i < len; i++) {
|
|
434
|
+
unsigned char c = (unsigned char)str[i];
|
|
435
|
+
buf[i] = (char)((c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
ret = rb_enc_interned_str(buf, (long)len, rb_utf8_encoding());
|
|
439
|
+
ALLOCV_END(tmp);
|
|
440
|
+
return ret;
|
|
441
|
+
#else
|
|
442
|
+
VALUE rb_str = rb_funcall(rb_utf8_str_new_cstr(str), rb_intern("downcase"), 1,
|
|
443
|
+
ID2SYM(rb_intern("ascii")));
|
|
444
|
+
return rb_funcall(rb_str, rb_intern("-@"), 0);
|
|
445
|
+
#endif
|
|
446
|
+
}
|
|
447
|
+
|
|
401
448
|
/* call-seq: stmt.column_name(index)
|
|
402
449
|
*
|
|
403
450
|
* Get the column name at +index+. 0 based.
|
|
@@ -425,7 +472,8 @@ column_name(VALUE self, VALUE index)
|
|
|
425
472
|
|
|
426
473
|
/* call-seq: stmt.column_decltype(index)
|
|
427
474
|
*
|
|
428
|
-
* Get the
|
|
475
|
+
* Get the declared type of the column at +index+, as a UTF-8 string. 0 based.
|
|
476
|
+
* Returns +nil+ if the column has no declared type, such as an expression.
|
|
429
477
|
*/
|
|
430
478
|
static VALUE
|
|
431
479
|
column_decltype(VALUE self, VALUE index)
|
|
@@ -440,7 +488,24 @@ column_decltype(VALUE self, VALUE index)
|
|
|
440
488
|
|
|
441
489
|
name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
|
|
442
490
|
|
|
443
|
-
if (name) { return
|
|
491
|
+
if (name) { return rb_utf8_str_new_cstr(name); }
|
|
492
|
+
return Qnil;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
static VALUE
|
|
496
|
+
column_decltype_downcased(VALUE self, VALUE index)
|
|
497
|
+
{
|
|
498
|
+
sqlite3StmtRubyPtr ctx;
|
|
499
|
+
const char *name;
|
|
500
|
+
|
|
501
|
+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
|
|
502
|
+
|
|
503
|
+
REQUIRE_LIVE_DB(ctx);
|
|
504
|
+
REQUIRE_OPEN_STMT(ctx);
|
|
505
|
+
|
|
506
|
+
name = sqlite3_column_decltype(ctx->st, (int)NUM2INT(index));
|
|
507
|
+
|
|
508
|
+
if (name) { return interned_downcased_utf8_cstr(name); }
|
|
444
509
|
return Qnil;
|
|
445
510
|
}
|
|
446
511
|
|
|
@@ -733,6 +798,7 @@ init_sqlite3_statement(void)
|
|
|
733
798
|
rb_define_method(cSqlite3Statement, "memused", memused, 0);
|
|
734
799
|
#endif
|
|
735
800
|
|
|
801
|
+
rb_define_private_method(cSqlite3Statement, "column_decltype_downcased", column_decltype_downcased, 1);
|
|
736
802
|
rb_define_private_method(cSqlite3Statement, "prepare", prepare, 2);
|
|
737
803
|
rb_define_private_method(cSqlite3Statement, "stats_as_hash", stats_as_hash, 0);
|
|
738
804
|
rb_define_private_method(cSqlite3Statement, "stat_for", stat_for, 1);
|
data/ext/sqlite3/timespec.h
CHANGED
|
@@ -15,6 +15,15 @@
|
|
|
15
15
|
(vsp)->tv_nsec += 1000000000L; \
|
|
16
16
|
} \
|
|
17
17
|
} while (0)
|
|
18
|
+
#define timespecadd(tsp, usp, vsp) \
|
|
19
|
+
do { \
|
|
20
|
+
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
|
21
|
+
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
|
22
|
+
if ((vsp)->tv_nsec >= 1000000000L) { \
|
|
23
|
+
(vsp)->tv_sec++; \
|
|
24
|
+
(vsp)->tv_nsec -= 1000000000L; \
|
|
25
|
+
} \
|
|
26
|
+
} while (0)
|
|
18
27
|
#define timespecafter(tsp, usp) \
|
|
19
28
|
(((tsp)->tv_sec > (usp)->tv_sec) || \
|
|
20
29
|
((tsp)->tv_sec == (usp)->tv_sec && (tsp)->tv_nsec > (usp)->tv_nsec))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/lib/sqlite3/resultset.rb
CHANGED
|
@@ -43,20 +43,26 @@ module SQLite3
|
|
|
43
43
|
@stmt.step
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
#
|
|
46
|
+
# With a block given, iterates over the rows of the result set, passing each
|
|
47
|
+
# to the block. Returns self.
|
|
48
|
+
# With no block given, returns a new Enumerator.
|
|
48
49
|
def each
|
|
50
|
+
return enum_for(__method__) unless block_given?
|
|
49
51
|
while (node = self.next)
|
|
50
52
|
yield node
|
|
51
53
|
end
|
|
54
|
+
self
|
|
52
55
|
end
|
|
53
56
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
57
|
+
# With a block given, iterates over the rows of the result set, passing each
|
|
58
|
+
# to the block as a hash. Returns self.
|
|
59
|
+
# With no block given, returns a new Enumerator.
|
|
56
60
|
def each_hash
|
|
61
|
+
return enum_for(__method__) unless block_given?
|
|
57
62
|
while (node = next_hash)
|
|
58
63
|
yield node
|
|
59
64
|
end
|
|
65
|
+
self
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
# Closes the statement that spawned this result set.
|
data/lib/sqlite3/statement.rb
CHANGED
|
@@ -42,6 +42,24 @@ module SQLite3
|
|
|
42
42
|
# See Database#execute for a description of the valid placeholder
|
|
43
43
|
# syntaxes.
|
|
44
44
|
#
|
|
45
|
+
# Type mapping from Ruby to SQLite3:
|
|
46
|
+
# - +nil+ → NULL
|
|
47
|
+
# - Integer → INTEGER (or REAL when outside the signed int64 range)
|
|
48
|
+
# - Float → REAL
|
|
49
|
+
# - SQLite3::Blob → BLOB
|
|
50
|
+
# - String with Encoding::ASCII_8BIT
|
|
51
|
+
# (a.k.a. BINARY) → BLOB
|
|
52
|
+
# - String with Encoding::UTF_16LE
|
|
53
|
+
# or Encoding::UTF_16BE → TEXT (bound as UTF-16)
|
|
54
|
+
# - String (all other encodings) → TEXT (re-encoded to UTF-8 if needed)
|
|
55
|
+
# - Any other type → raises RuntimeError
|
|
56
|
+
#
|
|
57
|
+
# Note: a String with Encoding::ASCII_8BIT (BINARY) is always bound as a
|
|
58
|
+
# BLOB, even when its bytes are all valid ASCII. If you want such a string
|
|
59
|
+
# compared or stored as TEXT, re-encode it before binding:
|
|
60
|
+
#
|
|
61
|
+
# stmt.bind_params(my_binary_str.encode(Encoding::UTF_8))
|
|
62
|
+
#
|
|
45
63
|
# Example:
|
|
46
64
|
#
|
|
47
65
|
# stmt = db.prepare( "select * from table where a=? and b=?" )
|
|
@@ -112,9 +130,9 @@ module SQLite3
|
|
|
112
130
|
!done?
|
|
113
131
|
end
|
|
114
132
|
|
|
115
|
-
# Return
|
|
116
|
-
# may execute the statement in order to
|
|
117
|
-
# a (potentially) expensive operation.
|
|
133
|
+
# Return a frozen array of the column names for this statement, as frozen
|
|
134
|
+
# UTF-8 strings. Note that this may execute the statement in order to
|
|
135
|
+
# obtain the metadata; this makes it a (potentially) expensive operation.
|
|
118
136
|
def columns
|
|
119
137
|
get_metadata unless @columns
|
|
120
138
|
@columns
|
|
@@ -128,9 +146,11 @@ module SQLite3
|
|
|
128
146
|
end
|
|
129
147
|
end
|
|
130
148
|
|
|
131
|
-
# Return
|
|
132
|
-
#
|
|
133
|
-
#
|
|
149
|
+
# Return a frozen array of the declared types of the columns in this
|
|
150
|
+
# statement, as frozen UTF-8 strings with ASCII letters downcased. A column
|
|
151
|
+
# with no declared type, such as an expression, has a +nil+ type. Note that
|
|
152
|
+
# this may execute the statement in order to obtain the metadata; this makes
|
|
153
|
+
# it a (potentially) expensive operation.
|
|
134
154
|
def types
|
|
135
155
|
must_be_open!
|
|
136
156
|
get_metadata unless @types
|
|
@@ -180,11 +200,10 @@ module SQLite3
|
|
|
180
200
|
def get_metadata
|
|
181
201
|
@columns = Array.new(column_count) do |column|
|
|
182
202
|
column_name column
|
|
183
|
-
end
|
|
203
|
+
end.freeze
|
|
184
204
|
@types = Array.new(column_count) do |column|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
end
|
|
205
|
+
column_decltype_downcased(column)
|
|
206
|
+
end.freeze
|
|
188
207
|
end
|
|
189
208
|
end
|
|
190
209
|
end
|
data/lib/sqlite3/version.rb
CHANGED