使用sqlite gem中的非默认sqlite3可执行文件

时间:2013-05-15 12:17:21

标签: ruby sqlite sequel

我已经编译了一个自定义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支持的情况下获得一个sianite3的debian / ubundu软件包?我找不到任何。

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

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

  4. 是否有另一种方法可以让sqlite gem看到我的原生可执行文件(或.so if(2)是否可行)。

  5. 提前谢谢你,

    ķ。

2 个答案:

答案 0 :(得分:0)

我终于成功了。要在编译本机扩展(如ICU对sqlite的支持)时安装gem,需要使用特定选项:

$ 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`

无论在两个'空'破折号之后发生什么,“ - ”都是参与宝石构建过程的参数。这假定sqlite3的src分布在/home/user/local/lib/sqlite-autoconf-3071602/

处未压缩

现在,因为我使用bundler,所以我想让它自动化。要做到这一点,可以使用以下命令:

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

...这意味着每当安装sqlite3 gem时,都会在构建过程中传递以下选项。这会创建一个~/.bundle/config文件,其中包含该gem的条目,例如该文件将具有:

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`

但是,这对我来说不合适。由于某种原因,~/.bundle/config中的条目不正确。我试着用几种组合引用和逃避,没有运气。最后,我通过添加以下内容在我的部署过程(shell脚本)中手动创建此条目:

$ 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

答案 1 :(得分:0)

我想使用window functions,它是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]]