1

我已经编译了一个自定义 sqlite3 可执行文件以启用对 ICU 的支持(排序规则:用重音符号排序等,用于 utf-8)。

我使用 rvm 并且 ruby​​ sqlite gem 似乎使用:

~/.rvm/gems/ruby-1.9.3-p392@project/gems/sqlite3-1.3.7/lib/sqlite3/sqlite3_native.so

我的数据库创建代码需要排序规则,所以当我使用 sqlite gem 时出现错误:

/home/user/.rvm/gems/ruby-1.9.3-p392@project/gems/sqlite3-1.3.7/lib/sqlite3/database.rb:91:in `initialize': SQLite3::SQLException: no such function: icu_load_collation (Sequel::DatabaseError)

...这是有道理的,因为默认的 sqlite 没有内置的排序规则。

当我直接使用我的自定义 sqlite3 可执行文件时,一切正常。

我的问题如下:

  1. 有没有办法获得已经内置 ICU 支持的 sqlite3 的 debian/ubundu 包?我找不到任何东西。

  2. 如果 (1) 不可能,我是否需要编译 sqlite3 并创建一个静态库而不是可执行文件?

  3. 如果(2)是可能的,我该如何正确地进行更改?我使用捆绑器并部署在另一台机器上。

  4. 有没有另一种方法可以让 sqlite gem 看到我的本机可执行文件(或者 .so 如果(2)是可能的)。

先感谢您,

K。

4

2 回答 2

1

I have finally made it work. To install a gem while compiling the native extensions (like ICU support for sqlite) with specific options one needs to do:

$ gem install sqlite3 --verbose --                                      \
    --with-opt-include=/home/user/local/lib/sqlite-autoconf-3071602/    \
    --with-opt-lib=/home/user/local/lib/sqlite-autoconf-3071602/.libs   \
    --with-cflags='-O3 -DSQLITE_ENABLE_ICU'                             \
    --with-cppflags=`icu-config --cppflags`                             \
    --with-ldflags=`icu-config --ldflags`

Whatever goes after the two 'empty' dashes "--" are parameters going to the build process of the gem. This assumes that the src distribution of sqlite3 was uncompressed at: /home/user/local/lib/sqlite-autoconf-3071602/

Now, since I use bundler I wanted this to be automated. To do that one can use the following command:

bundle config build.sqlite3 --with-opt-include=/home/user/local/lib/sqlite-autoconf-3071602/ ...

... which means that whenever sqlite3 gem is installed pass the following options in the build process. That creates a ~/.bundle/config file with an entry for that gem, e.g. the file would have:

BUNDLE_BUILD__SQLITE3: --with-opt-include=/home/karask/local/lib/sqlite-autoconf-3071602/  --with-opt-lib=/home/karask/local/lib/sqlite-autoconf-3071602/.libs  --with-cflags='-O3 -DSQLITE_ENABLE_ICU' --with-cppflags=`icu-config --cppflags` --with-ldflags=`icu-config --ldflags`

However, that wasn't working properly for me. For some reason the entry in ~/.bundle/config wasn't correct. I tried quoting and escaping in several combinations with no luck. At the end I create this entry manually in my deployment process (a shell script) by adding the following:

$ mkdir ~/.bundle
$ echo "BUNDLE_BUILD__SQLITE3: --with-opt-include=/home/user/local/lib/sqlite-autoconf-3071602/  --with-opt-lib=/home/user/local/lib/sqlite-autoconf-3071602/.libs  --with-cflags='-O3 -DSQLITE_ENABLE_ICU' --with-cppflags=`icu-config --cppflags` --with-ldflags=`icu-config --ldflags`" > ~/.bundle/config
于 2013-05-19T16:50:44.717 回答
0

我想使用Ubuntu 18.10 中附带的 SQLite 3.24.0 中不存在的窗口函数,这是一种编译 SQLite 3.28.0 的方法(Ubuntu 19.04 附带 SQLite 3.27):

# it is a good idea to have system package installed to make sure you have dependencies necessary:
sudo apt install libsqlite3-dev

wget https://sqlite.org/src/tarball/sqlite.tar.gz?r=release -O sqlite.tar.gz
tar xzf sqlite.tar.gz

mkdir build
cd build
../sqlite/configure
export CFLAGS='-DSQLITE_ENABLE_COLUMN_METADATA -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_LOAD_EXTENSION -DSQLITE_ENABLE_PREUPDATE_HOOK -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION -DSQLITE_ENABLE_UNLOCK_NOTIFY -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT -DSQLITE_MAX_SCHEMA_RETRY=25 -DSQLITE_MAX_VARIABLE_NUMBER=250000 -DSQLITE_OMIT_LOOKASIDE -DSQLITE_SECURE_DELETE -DSQLITE_SOUNDEX -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DHAVE_USLEEP -DHAVE_READLINE -DHAVE_ISNAN -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_THREADSAFE=1 -DSQLITE_ENABLE_FTS4'
make OPTS="$CFLAGS"

gem install sqlite3 --verbose -- \
    --with-sqlite3-include=`readlink -f .` \
    --with-sqlite3-lib=`readlink -f .libs` \
    --with-cflags="$CFLAGS"

可以通过查看 gem 编译的 sqlite 版本

require 'sqlite3'
puts SQLite3::SQLITE_VERSION #=> 3.28.0

或者只是尝试使用窗口函数:

require 'sqlite3'
require 'awesome_print'

db = SQLite3::Database.new(':memory:')
db.results_as_hash = true

db.execute <<~SQL
create table tab (
  `id` integer,
  `value` varchar(3)
)
SQL

db.execute <<~SQL
insert into tab
  (`id`, `value`)
values
  ('1', 'yes'),
  ('3', 'yes'),
  ('4', 'no' ),
  ('6', 'yes'),
  ('9', 'yes')
SQL

ap db.execute <<~SQL
select
  *
, row_number() over(order by id) as row_number
from tab
where value = "yes"
SQL

至于 unicode 支持 (ICU),我更喜欢将其安装为可加载扩展:

sudo apt install libicu-dev libsqlite3-dev

wget "https://sqlite.org/src/raw/ext/icu/icu.c?name=b2732aef0b076e4276d9b39b5a33cec7a05e1413" -O icu.c
sed -i 's/sqlite3_icu_init/sqlite3_sqliteicu_init/g' icu.c

gcc -shared icu.c -fPIC `icu-config --ldflags` -o libSqlite3Icu.so

在此之后可以从 ruby​​ 中使用它:

require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.enable_load_extension(1)
db.load_extension("/path/to/libSqlite3Icu.so")
db.enable_load_extension(0)

db.execute <<~SQL
select "Ы" like "ы"
SQL
# should be [[1]]
于 2019-06-15T21:19:32.243 回答