mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-19 15:05:47 +01:00
Merge 'Adjust vtab schema creation to display the underlying columns' from Preston Thorpe
### The problem: Sqlite displays the column names of the underlying vtab module when displaying the `.schema`  Previously limbo omitted this, which makes it difficult for the user to see what/how many columns the module's table has. This matches sqlite's behavior by fetching the module's schema when the schema entry is being inserted in translation.  Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com> Closes #1168
This commit is contained in:
@@ -97,7 +97,7 @@ pub fn translate(
|
||||
ast::Stmt::CreateTrigger { .. } => bail_parse_error!("CREATE TRIGGER not supported yet"),
|
||||
ast::Stmt::CreateView { .. } => bail_parse_error!("CREATE VIEW not supported yet"),
|
||||
ast::Stmt::CreateVirtualTable(vtab) => {
|
||||
translate_create_virtual_table(*vtab, schema, query_mode)?
|
||||
translate_create_virtual_table(*vtab, schema, query_mode, &syms)?
|
||||
}
|
||||
ast::Stmt::Delete(delete) => {
|
||||
let Delete {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::ast;
|
||||
use crate::ext::VTabImpl;
|
||||
use crate::schema::Schema;
|
||||
use crate::schema::Table;
|
||||
use crate::storage::pager::CreateBTreeFlags;
|
||||
@@ -11,8 +13,10 @@ use crate::util::PRIMARY_KEY_AUTOMATIC_INDEX_NAME_PREFIX;
|
||||
use crate::vdbe::builder::CursorType;
|
||||
use crate::vdbe::insn::{CmpInsFlags, Insn};
|
||||
use crate::LimboError;
|
||||
use crate::SymbolTable;
|
||||
use crate::{bail_parse_error, Result};
|
||||
|
||||
use limbo_ext::VTabKind;
|
||||
use limbo_sqlite3_parser::ast::{fmt::ToTokens, CreateVirtualTable};
|
||||
|
||||
pub fn translate_create_table(
|
||||
@@ -396,7 +400,7 @@ fn create_table_body_to_str(tbl_name: &ast::QualifiedName, body: &ast::CreateTab
|
||||
sql
|
||||
}
|
||||
|
||||
fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String {
|
||||
fn create_vtable_body_to_str(vtab: &CreateVirtualTable, module: Rc<VTabImpl>) -> String {
|
||||
let args = if let Some(args) = &vtab.args {
|
||||
args.iter()
|
||||
.map(|arg| arg.to_string())
|
||||
@@ -410,8 +414,25 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String {
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let ext_args = vtab
|
||||
.args
|
||||
.as_ref()
|
||||
.unwrap_or(&vec![])
|
||||
.iter()
|
||||
.map(|a| limbo_ext::Value::from_text(a.to_string()))
|
||||
.collect::<Vec<_>>();
|
||||
let schema = module
|
||||
.implementation
|
||||
.init_schema(ext_args)
|
||||
.unwrap_or_default();
|
||||
let vtab_args = if let Some(first_paren) = schema.find('(') {
|
||||
let closing_paren = schema.rfind(')').unwrap_or_default();
|
||||
&schema[first_paren..=closing_paren]
|
||||
} else {
|
||||
"()"
|
||||
};
|
||||
format!(
|
||||
"CREATE VIRTUAL TABLE {} {} USING {}{}",
|
||||
"CREATE VIRTUAL TABLE {} {} USING {}{}\n /*{}{}*/",
|
||||
vtab.tbl_name.name.0,
|
||||
if_not_exists,
|
||||
vtab.module_name.0,
|
||||
@@ -419,7 +440,9 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String {
|
||||
String::new()
|
||||
} else {
|
||||
format!("({})", args)
|
||||
}
|
||||
},
|
||||
vtab.tbl_name.name.0,
|
||||
vtab_args
|
||||
)
|
||||
}
|
||||
|
||||
@@ -427,6 +450,7 @@ pub fn translate_create_virtual_table(
|
||||
vtab: CreateVirtualTable,
|
||||
schema: &Schema,
|
||||
query_mode: QueryMode,
|
||||
syms: &SymbolTable,
|
||||
) -> Result<ProgramBuilder> {
|
||||
let ast::CreateVirtualTable {
|
||||
if_not_exists,
|
||||
@@ -438,7 +462,12 @@ pub fn translate_create_virtual_table(
|
||||
let table_name = tbl_name.name.0.clone();
|
||||
let module_name_str = module_name.0.clone();
|
||||
let args_vec = args.clone().unwrap_or_default();
|
||||
|
||||
let Some(vtab_module) = syms.vtab_modules.get(&module_name_str) else {
|
||||
bail_parse_error!("no such module: {}", module_name_str);
|
||||
};
|
||||
if !vtab_module.module_kind.eq(&VTabKind::VirtualTable) {
|
||||
bail_parse_error!("module {} is not a virtual table", module_name_str);
|
||||
};
|
||||
if schema.get_table(&table_name).is_some() && *if_not_exists {
|
||||
let mut program = ProgramBuilder::new(ProgramBuilderOpts {
|
||||
query_mode,
|
||||
@@ -464,7 +493,6 @@ pub fn translate_create_virtual_table(
|
||||
let start_offset = program.offset();
|
||||
let module_name_reg = program.emit_string8_new_reg(module_name_str.clone());
|
||||
let table_name_reg = program.emit_string8_new_reg(table_name.clone());
|
||||
|
||||
let args_reg = if !args_vec.is_empty() {
|
||||
let args_start = program.alloc_register();
|
||||
|
||||
@@ -490,7 +518,6 @@ pub fn translate_create_virtual_table(
|
||||
table_name: table_name_reg,
|
||||
args_reg,
|
||||
});
|
||||
|
||||
let table = schema.get_btree_table(SQLITE_TABLEID).unwrap();
|
||||
let sqlite_schema_cursor_id = program.alloc_cursor_id(
|
||||
Some(SQLITE_TABLEID.to_owned()),
|
||||
@@ -501,7 +528,7 @@ pub fn translate_create_virtual_table(
|
||||
root_page: 1usize.into(),
|
||||
});
|
||||
|
||||
let sql = create_vtable_body_to_str(&vtab);
|
||||
let sql = create_vtable_body_to_str(&vtab, vtab_module.clone());
|
||||
emit_schema_entry(
|
||||
&mut program,
|
||||
sqlite_schema_cursor_id,
|
||||
|
||||
@@ -345,7 +345,7 @@ def test_kv():
|
||||
limbo.execute_dot("INSERT INTO other values (23,32,23);")
|
||||
limbo.run_test_fn(
|
||||
"create virtual table t using kv_store;",
|
||||
lambda res: "Module kv_store not found" in res,
|
||||
lambda res: "Parse error: no such module: kv_store" in res,
|
||||
)
|
||||
limbo.execute_dot(f".load {ext_path}")
|
||||
limbo.execute_dot(
|
||||
|
||||
Reference in New Issue
Block a user