Skip to content
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

Add support to updatable virtual tables #1141

Merged
merged 8 commits into from
Apr 4, 2022
Merged

Conversation

gwenn
Copy link
Collaborator

@gwenn gwenn commented Mar 17, 2022

Fix #730, #900

TODO
[X] simple implementation at least for test / example.
[X] eponymous updatable VTab

@gwenn gwenn requested a review from thomcc March 17, 2022 20:10
@codecov
Copy link

codecov bot commented Mar 17, 2022

Codecov Report

Merging #1141 (a4186ad) into master (5e2c103) will increase coverage by 0.68%.
The diff coverage is 77.97%.

@@            Coverage Diff             @@
##           master    #1141      +/-   ##
==========================================
+ Coverage   78.21%   78.89%   +0.68%     
==========================================
  Files          47       48       +1     
  Lines        5927     6028     +101     
==========================================
+ Hits         4636     4756     +120     
+ Misses       1291     1272      -19     
Impacted Files Coverage Δ
src/vtab/mod.rs 59.23% <59.25%> (+8.04%) ⬆️
src/vtab/vtablog.rs 86.11% <86.11%> (ø)
src/vtab/array.rs 84.93% <100.00%> (ø)
src/vtab/csvtab.rs 63.22% <100.00%> (-1.41%) ⬇️
src/vtab/series.rs 83.08% <100.00%> (ø)
tests/vtab.rs 80.64% <100.00%> (ø)
src/lib.rs 89.64% <0.00%> (-0.46%) ⬇️
src/statement.rs 91.97% <0.00%> (ø)
libsqlite3-sys/src/lib.rs 100.00% <0.00%> (ø)
tests/deny_single_threaded_sqlite_config.rs 100.00% <0.00%> (ø)
... and 3 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5e2c103...a4186ad. Read the comment docs.

@gwenn
Copy link
Collaborator Author

gwenn commented Mar 19, 2022

I don't understand why 6d885c8 doesn't compile.
Maybe because of rust-lang/rust#60502 ?

@thomcc
Copy link
Member

thomcc commented Mar 19, 2022

We might have to explicitly put it as a const or something, and return a reference to that. Const promotion doesn't work that reliably.

It's possible that keeping this const isn't viable also.

@gwenn gwenn marked this pull request as ready for review March 20, 2022 11:26
Copy link
Member

@thomcc thomcc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good but needs a couple changes.

pub fn read_only_module<'vtab, T: CreateVTab<'vtab>>() -> &'static Module<'vtab, T> {
// The xConnect and xCreate methods do the same thing, but they must be
// different so that the virtual table is not an eponymous virtual table.
macro_rules! module {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good idea for how to do this.

@@ -1153,6 +1203,49 @@ where
}
}

unsafe extern "C" fn rust_update<'vtab, T: 'vtab>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this lands I'm going to do a follow-up to fix FFI-panics in some code (including this).

Our current code doesn't handle it correctly either, FWIW.

src/vtab/vtablog.rs Show resolved Hide resolved
) -> Result<(String, VTabLog)> {
static N_INST: AtomicUsize = AtomicUsize::new(1);
let i_inst = N_INST.fetch_add(1, Ordering::SeqCst);
println!(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's definitely not okay for us to println! for stuff like this. Even eprintln! is dodgy since it will panic if the stderr is closed (for example, inside a daemon). I've vaguely wanted rusqlite to pull in the log crate for a while now, and this seems like a reasonable place to start.

Edit: Never mind, this is behind #[cfg(test)]. I didn't notice it. I think it might be better as an example than a test, but this is fine.

/// not used
///
/// SQLite >= 3.9.0
EponymousOnly,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add a check for crate::version_number() >= 3009000 for attempts to register an EponymousOnly module, and return an Err(...).

Prior to 3.9.0 SQLite will crash on eponymous-only modules, because it doesn't check for xCreate being NULL.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://sqlite.org/vtab.html#eponymous_only_virtual_tables

Note that prior to version 3.9.0 (2015-10-14), SQLite did not check the xCreate method for NULL before invoking it. So if an eponymous-only virtual table is registered with SQLite version 3.8.11.1 (2015-07-29) or earlier and a CREATE VIRTUAL TABLE command is attempted against that virtual table module, a jump to a NULL pointer will occur, resulting in a crash.

A crash seems safe to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crash from null pointer dereference is undefined behavior. Absolutely not safe. Just because it is deterministic and is not exploitable does not mean it's memory safe.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -57,6 +57,19 @@ use crate::{str_to_cstring, Connection, Error, InnerConnection, Result};
// ffi::sqlite3_vtab => VTab
// ffi::sqlite3_vtab_cursor => VTabCursor

/// Virtual table kind
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs better docs. Can you use this? Do a quick read-through of it to make sure I didn't make any obvious mistakes, also.

/// Virtual table kind, indicating whether or not the table is
/// [eponymous](https://sqlite.org/vtab.html#eponymous_virtual_tables).
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VTabKind {
    /// Non-eponymous tables, which are the most flexible.
    Default,
    /// Eponymous tables exist implicitly in the main schema of the database,
    /// and do not require setup such as `CREATE VIRTUAL TABLE` to be used.
    ///
    /// These should implement [`CreateVTab::create`] and [`VTab::connect`]
    /// identically. (Which is the default behavior if [`CreateVTab::create`] is
    /// not explicitly overridden)
    Eponymous,
    /// Eponymous-only tables are tables which may only be used eponymously, and
    /// cannot be used with `CREATE VIRTUAL TABLE`.
    ///
    /// This is often useful for table valued functions, although note that this
    /// prevents use as a temporary table, in patterns like the following:
    ///
    /// ```sql
    /// CREATE VIRTUAL TABLE temp.something USING my_vtab(args, here);
    /// ```
    ///
    /// But whether or not this pattern makes sense to support depends on the
    /// implementation of your table.
    ///
    /// Eponymous-only tables will not have the [`CreateVTab::create`] and
    /// [`CreateVTab::destroy`] methods called. [`VTab::connect`] will be used
    /// instead (and cleanup will be performed by [`Drop::drop`]).
    ///
    /// If the SQLite version is older than 3.9.0, `rusqlite` will produce an
    /// error when you attempt to register a `EponymousOnly` virtual table
    EponymousOnly,
}

Copy link
Member

@thomcc thomcc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. i'll have a follow-up PR up for the unwinding shortly.

@thomcc thomcc merged commit 33e5f12 into rusqlite:master Apr 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Why is there no UpdateVTab?
2 participants