From 5c0e37bbe19b382f722ed7aafd4a5dcc21b8be4a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 22 Aug 2024 11:49:19 -0700 Subject: [PATCH] Support creating VIRTUAL tables on SQLite via the create_table :using option --- CHANGELOG | 2 ++ lib/sequel/adapters/shared/sqlite.rb | 4 +++- lib/sequel/database/schema_methods.rb | 2 ++ spec/adapters/sqlite_spec.rb | 13 +++++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 4e3c75e1b..7b536bde8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === master +* Support creating VIRTUAL tables on SQLite via the create_table :using option (jeremyevans) + * Support json_{exists,value,query} on PostgreSQL 17+ in the pg_json_ops extension (jeremyevans) * Remove documentation from the gem to reduce gem size by 25% (jeremyevans) diff --git a/lib/sequel/adapters/shared/sqlite.rb b/lib/sequel/adapters/shared/sqlite.rb index 6cfba71e1..61931099d 100644 --- a/lib/sequel/adapters/shared/sqlite.rb +++ b/lib/sequel/adapters/shared/sqlite.rb @@ -349,7 +349,7 @@ def connection_pragmas ps end - # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options + # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options, and VIRTUAL tables with :using option. def create_table_sql(name, generator, options) if options[:strict] && options[:without_rowid] "#{super} STRICT, WITHOUT ROWID" @@ -357,6 +357,8 @@ def create_table_sql(name, generator, options) "#{super} STRICT" elsif options[:without_rowid] "#{super} WITHOUT ROWID" + elsif options[:using] + "CREATE VIRTUAL TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{create_table_table_name_sql(name, options)} USING #{options[:using]}" else super end diff --git a/lib/sequel/database/schema_methods.rb b/lib/sequel/database/schema_methods.rb index c7cdd0c9f..0af43cb41 100644 --- a/lib/sequel/database/schema_methods.rb +++ b/lib/sequel/database/schema_methods.rb @@ -191,6 +191,8 @@ def create_join_table?(hash, options=OPTS) # The +any+ type is treated like a SQLite column in a non-strict table, # allowing any type of data to be stored. This option is supported on # SQLite 3.37.0+. + # :using :: Create a VIRTUAL table with the given USING clause. The value should be + # a string, as it is used directly in the SQL query. # :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special # 'rowid' column, that uniquely identifies that row within the table. # If this option is used, the 'rowid' column is omitted, which can diff --git a/spec/adapters/sqlite_spec.rb b/spec/adapters/sqlite_spec.rb index c4ef55479..1258121db 100644 --- a/spec/adapters/sqlite_spec.rb +++ b/spec/adapters/sqlite_spec.rb @@ -29,6 +29,19 @@ @db.sqlite_version.must_be_kind_of(Integer) end + it "should support creating virtual tables via the create_table :using option" do + if @db['PRAGMA compile_options'].map(:compile_options).include?('ENABLE_FTS5') + @db.create_table(:fk, using: 'fts5(c)') + @db[:fk].insert(:c=>'foo bar') + @db[:fk].where(fk: 'foo').get(:c).must_equal 'foo bar' + @db[:fk].where(fk: 'bar').get(:c).must_equal 'foo bar' + @db[:fk].where(fk: 'baz').must_be_empty + + @db.create_table(:fk, using: 'fts5(c)', if_not_exists: true) + @db[:fk].where(fk: 'foo').get(:c).must_equal 'foo bar' + end + end + it "should support dropping noncomposite unique constraint" do @db.create_table(:fk) do primary_key :id