New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLite FTS5 Virtual Table Default Primary Key #1748

Closed
0xcaff opened this Issue Jun 1, 2018 · 1 comment

Comments

Projects
None yet
1 participant
@0xcaff

0xcaff commented Jun 1, 2018

Setup

CREATE VIRTUAL TABLE email USING fts5(sender, title, body);

Versions

  • Rust: rustc 1.26.0 (a77568041 2018-05-07)
  • Diesel: diesel 1.2.0
  • Database: sqlite
  • Operating System linux

Feature Flags

  • diesel: chrono, sqlite

Problem Description

Trying to infer the schema for the table above fails.

What are you trying to accomplish?

I'm trying to use SQLite's FTS5 with diesel.

What is the expected output?

I'd expect diesel to use the rowid field as the default PRIMARY KEY for sql tables without explicit primary keys.

The FTS5 docs:

It is an error to add types, constraints or PRIMARY KEY declarations to a CREATE VIRTUAL TABLE statement used to create an FTS5 table. [...] Like any other table with no PRIMARY KEY declaration, an FTS5 table has an implicit INTEGER PRIMARY KEY field named rowid.

What is the actual output?

[me@falcon core]$ ~/.cargo/bin/diesel migration run
Running migration 2018-05-14-200933_setup
[me@falcon core]$ ~/.cargo/bin/diesel print-schema
Diesel only supports tables with primary keys. Table email has no primary key

Related Issues

Workaround

Use print-schema's blacklist and exclude all tables related to the virtual table, the declare the table explicitly.

[me@falcon core]$ ~/.cargo/bin/diesel print-schema --blacklist email{,_config,_content,_data,_docsize,_idx} > src/database.rs 
table! {
	email(rowid) {
		rowid -> Integer,
		sender -> Text,
		title -> Text,
		body -> Text,
	}
}

@0xcaff 0xcaff referenced this issue Jun 1, 2018

Open

Better Search #47

@0xcaff

This comment has been minimized.

0xcaff commented Jun 1, 2018

Hm, on second thought, fts virtual tables are special enough that the workaround is probably the best way to go. Here's a minimal example of using FTS.

Here's a minimal example of using full text search:

main.rs

#[macro_use]
extern crate diesel;

mod database;

use database::email;
use diesel::prelude::*;

fn main() {
    let conn = SqliteConnection::establish("./test.sqlite").unwrap();

    let values = email::table
        .select((email::rowid, email::rank))
        .filter(email::whole_row.eq("john"))
        .first::<(i32, f32)>(&conn)
        .unwrap();

    println!("{:?}", values);
}

database.rs

table! {
    email(rowid) {
        rowid -> Integer,

        #[sql_name = "email"]
        whole_row -> Text,
        rank -> Float,
    }
}

up.sql

CREATE VIRTUAL TABLE email USING fts5(sender, title, body);

INSERT INTO email (sender, title, body) VALUES ('John Doe', 'Hello World', 'Welcome john to the land of the awesome');

Running

/usr/bin/cargo run --color=always --package diesel-fts --bin diesel-fts
   Compiling diesel-fts v0.1.0 (file:///home/me/projects/diesel-fts)
    Finished dev [unoptimized + debuginfo] target(s) in 1.39 secs
     Running `target/debug/diesel-fts`
(1, -0.000001375)

Process finished with exit code 0

@0xcaff 0xcaff closed this Jun 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment