mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-07-07 12:35:00 +00:00
Rename limbo_sqlite3_parser
crate to turso_sqlite3_parser
This commit is contained in:
parent
796b03b048
commit
725c3e4ddc
63 changed files with 162 additions and 162 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
@ -1837,7 +1837,6 @@ dependencies = [
|
|||
"dirs 6.0.0",
|
||||
"env_logger 0.10.2",
|
||||
"hex",
|
||||
"limbo_sqlite3_parser",
|
||||
"log",
|
||||
"notify",
|
||||
"rand 0.8.5",
|
||||
|
@ -1850,6 +1849,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"turso_core",
|
||||
"turso_sqlite3_parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1865,27 +1865,6 @@ dependencies = [
|
|||
"turso_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"cc",
|
||||
"env_logger 0.11.7",
|
||||
"fallible-iterator",
|
||||
"indexmap 2.8.0",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"serde",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_sqlite_test_ext"
|
||||
version = "0.1.0-pre.2"
|
||||
|
@ -3228,7 +3207,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"criterion",
|
||||
"fallible-iterator",
|
||||
"limbo_sqlite3_parser",
|
||||
"turso_sqlite3_parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3747,7 +3726,6 @@ dependencies = [
|
|||
"limbo_percentile",
|
||||
"limbo_regexp",
|
||||
"limbo_series",
|
||||
"limbo_sqlite3_parser",
|
||||
"limbo_time",
|
||||
"limbo_uuid",
|
||||
"lru",
|
||||
|
@ -3777,6 +3755,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"turso_ext",
|
||||
"turso_macros",
|
||||
"turso_sqlite3_parser",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
|
@ -3819,6 +3798,27 @@ dependencies = [
|
|||
"turso_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "turso_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"cc",
|
||||
"env_logger 0.11.7",
|
||||
"fallible-iterator",
|
||||
"indexmap 2.8.0",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"serde",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.10"
|
||||
|
|
|
@ -50,7 +50,7 @@ turso_macros = { path = "macros", version = "0.1.0-pre.2" }
|
|||
limbo_percentile = { path = "extensions/percentile", version = "0.1.0-pre.2" }
|
||||
limbo_regexp = { path = "extensions/regexp", version = "0.1.0-pre.2" }
|
||||
limbo_series = { path = "extensions/series", version = "0.1.0-pre.2" }
|
||||
limbo_sqlite3_parser = { path = "vendored/sqlite3-parser", version = "0.1.0-pre.2" }
|
||||
turso_sqlite3_parser = { path = "vendored/sqlite3-parser", version = "0.1.0-pre.2" }
|
||||
limbo_time = { path = "extensions/time", version = "0.1.0-pre.2" }
|
||||
limbo_uuid = { path = "extensions/uuid", version = "0.1.0-pre.2" }
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
|
|
|
@ -52,7 +52,7 @@ cfg_block = "0.1.1"
|
|||
fallible-iterator = "0.3.0"
|
||||
hex = "0.4.3"
|
||||
libc = { version = "0.2.172", optional = true }
|
||||
limbo_sqlite3_parser = { workspace = true }
|
||||
turso_sqlite3_parser = { workspace = true }
|
||||
thiserror = "1.0.61"
|
||||
getrandom = { version = "0.2.15" }
|
||||
regex = "1.11.1"
|
||||
|
|
|
@ -14,7 +14,7 @@ pub enum LimboError {
|
|||
ParseError(String),
|
||||
#[error(transparent)]
|
||||
#[diagnostic(transparent)]
|
||||
LexerError(#[from] limbo_sqlite3_parser::lexer::sql::Error),
|
||||
LexerError(#[from] turso_sqlite3_parser::lexer::sql::Error),
|
||||
#[error("Conversion error: {0}")]
|
||||
ConversionError(String),
|
||||
#[error("Env variable error: {0}")]
|
||||
|
|
|
@ -50,7 +50,6 @@ pub use io::{
|
|||
Buffer, Completion, CompletionType, File, MemoryIO, OpenFlags, PlatformIO, SyscallIO,
|
||||
WriteCompletion, IO,
|
||||
};
|
||||
use limbo_sqlite3_parser::{ast, ast::Cmd, lexer::sql::Parser};
|
||||
use parking_lot::RwLock;
|
||||
use schema::Schema;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
@ -80,6 +79,7 @@ pub use storage::{
|
|||
};
|
||||
use tracing::{instrument, Level};
|
||||
use translate::select::prepare_select_plan;
|
||||
use turso_sqlite3_parser::{ast, ast::Cmd, lexer::sql::Parser};
|
||||
pub use types::RefValue;
|
||||
pub use types::Value;
|
||||
use util::parse_schema_rows;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{Connection, LimboError, Statement, StepResult, Value};
|
||||
use bitflags::bitflags;
|
||||
use limbo_sqlite3_parser::ast::PragmaName;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use turso_sqlite3_parser::ast::PragmaName;
|
||||
|
||||
bitflags! {
|
||||
// Flag names match those used in SQLite:
|
||||
|
|
|
@ -4,15 +4,15 @@ use crate::{util::normalize_ident, Result};
|
|||
use crate::{LimboError, VirtualTable};
|
||||
use core::fmt;
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use limbo_sqlite3_parser::ast::{self, ColumnDefinition, Expr, Literal, SortOrder, TableOptions};
|
||||
use limbo_sqlite3_parser::{
|
||||
ast::{Cmd, CreateTableBody, QualifiedName, ResultColumn, Stmt},
|
||||
lexer::sql::Parser,
|
||||
};
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use tracing::trace;
|
||||
use turso_sqlite3_parser::ast::{self, ColumnDefinition, Expr, Literal, SortOrder, TableOptions};
|
||||
use turso_sqlite3_parser::{
|
||||
ast::{Cmd, CreateTableBody, QualifiedName, ResultColumn, Stmt},
|
||||
lexer::sql::Parser,
|
||||
};
|
||||
|
||||
const SCHEMA_TABLE_NAME: &str = "sqlite_schema";
|
||||
const SCHEMA_TABLE_NAME_ALT: &str = "sqlite_master";
|
||||
|
@ -389,7 +389,7 @@ fn create_table(
|
|||
is_strict = options.contains(TableOptions::STRICT);
|
||||
if let Some(constraints) = constraints {
|
||||
for c in constraints {
|
||||
if let limbo_sqlite3_parser::ast::TableConstraint::PrimaryKey {
|
||||
if let turso_sqlite3_parser::ast::TableConstraint::PrimaryKey {
|
||||
columns, ..
|
||||
} = c.constraint
|
||||
{
|
||||
|
@ -406,7 +406,7 @@ fn create_table(
|
|||
primary_key_columns
|
||||
.push((col_name, column.order.unwrap_or(SortOrder::Asc)));
|
||||
}
|
||||
} else if let limbo_sqlite3_parser::ast::TableConstraint::Unique {
|
||||
} else if let turso_sqlite3_parser::ast::TableConstraint::Unique {
|
||||
columns,
|
||||
conflict_clause,
|
||||
} = c.constraint
|
||||
|
@ -490,7 +490,7 @@ fn create_table(
|
|||
let mut collation = None;
|
||||
for c_def in &col_def.constraints {
|
||||
match &c_def.constraint {
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::PrimaryKey {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::PrimaryKey {
|
||||
order: o,
|
||||
..
|
||||
} => {
|
||||
|
@ -499,20 +499,20 @@ fn create_table(
|
|||
order = *o;
|
||||
}
|
||||
}
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::NotNull { .. } => {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::NotNull { .. } => {
|
||||
notnull = true;
|
||||
}
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Default(expr) => {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Default(expr) => {
|
||||
default = Some(expr.clone())
|
||||
}
|
||||
// TODO: for now we don't check Resolve type of unique
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Unique(on_conflict) => {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Unique(on_conflict) => {
|
||||
if on_conflict.is_some() {
|
||||
unimplemented!("ON CONFLICT not implemented");
|
||||
}
|
||||
unique = true;
|
||||
}
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Collate { collation_name } => {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Collate { collation_name } => {
|
||||
collation = Some(CollationSeq::new(collation_name.0.as_str())?);
|
||||
}
|
||||
// Collate
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_sqlite3_parser::ast;
|
||||
use turso_sqlite3_parser::ast;
|
||||
|
||||
use crate::{
|
||||
function::AggFunc,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use fallible_iterator::FallibleIterator as _;
|
||||
use limbo_sqlite3_parser::{ast, lexer::sql::Parser};
|
||||
use turso_sqlite3_parser::{ast, lexer::sql::Parser};
|
||||
|
||||
use crate::{
|
||||
function::{AlterTableFunc, Func},
|
||||
|
|
|
@ -5,9 +5,9 @@ use crate::vdbe::builder::{CursorType, ProgramBuilder};
|
|||
use crate::vdbe::insn::Insn;
|
||||
use crate::vdbe::BranchOffset;
|
||||
use crate::SymbolTable;
|
||||
use limbo_sqlite3_parser::ast::{CompoundOperator, SortOrder};
|
||||
use std::sync::Arc;
|
||||
use tracing::instrument;
|
||||
use turso_sqlite3_parser::ast::{CompoundOperator, SortOrder};
|
||||
|
||||
use tracing::Level;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::translate::plan::{DeletePlan, Operation, Plan};
|
|||
use crate::translate::planner::{parse_limit, parse_where};
|
||||
use crate::vdbe::builder::{ProgramBuilder, ProgramBuilderOpts, QueryMode, TableRefIdCounter};
|
||||
use crate::{schema::Schema, Result, SymbolTable};
|
||||
use limbo_sqlite3_parser::ast::{Expr, Limit, QualifiedName};
|
||||
use turso_sqlite3_parser::ast::{Expr, Limit, QualifiedName};
|
||||
|
||||
use super::plan::{ColumnUsedMask, IterationDirection, JoinedTable, TableReferences};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use core::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use limbo_sqlite3_parser::{
|
||||
use turso_sqlite3_parser::{
|
||||
ast::{SortOrder, TableInternalId},
|
||||
to_sql_string::{ToSqlContext, ToSqlString},
|
||||
};
|
||||
|
@ -315,7 +315,7 @@ impl ToSqlString for Plan {
|
|||
}
|
||||
|
||||
impl ToSqlString for JoinedTable {
|
||||
fn to_sql_string<C: limbo_sqlite3_parser::to_sql_string::ToSqlContext>(
|
||||
fn to_sql_string<C: turso_sqlite3_parser::to_sql_string::ToSqlContext>(
|
||||
&self,
|
||||
_context: &C,
|
||||
) -> String {
|
||||
|
@ -349,7 +349,7 @@ impl ToSqlString for JoinedTable {
|
|||
|
||||
// TODO: currently cannot print the original CTE as it is optimized into a subquery
|
||||
impl ToSqlString for SelectPlan {
|
||||
fn to_sql_string<C: limbo_sqlite3_parser::to_sql_string::ToSqlContext>(
|
||||
fn to_sql_string<C: turso_sqlite3_parser::to_sql_string::ToSqlContext>(
|
||||
&self,
|
||||
context: &C,
|
||||
) -> String {
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
use std::rc::Rc;
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, Expr};
|
||||
use tracing::{instrument, Level};
|
||||
use turso_sqlite3_parser::ast::{self, Expr};
|
||||
|
||||
use super::aggregation::emit_ungrouped_aggregation;
|
||||
use super::expr::translate_expr;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use limbo_sqlite3_parser::ast::{self, Expr, UnaryOperator};
|
||||
use tracing::{instrument, Level};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, UnaryOperator};
|
||||
|
||||
use super::emitter::Resolver;
|
||||
use super::optimizer::Optimizable;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use limbo_sqlite3_parser::ast;
|
||||
use turso_sqlite3_parser::ast;
|
||||
|
||||
use crate::translate::expr::{walk_expr, WalkControl};
|
||||
use crate::translate::plan::ResultSetColumn;
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
insn::{IdxInsertFlags, Insn, RegisterOrLiteral},
|
||||
},
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{self, Expr, Id, SortOrder, SortedColumn};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, Id, SortOrder, SortedColumn};
|
||||
|
||||
use super::schema::{emit_schema_entry, SchemaEntryType, SQLITE_TABLEID};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use limbo_sqlite3_parser::ast::{
|
||||
use turso_sqlite3_parser::ast::{
|
||||
DistinctNames, Expr, InsertBody, OneSelect, QualifiedName, ResolveType, ResultColumn, With,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use limbo_sqlite3_parser::ast::{self, SortOrder};
|
||||
use turso_ext::VTabKind;
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder};
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
|
@ -43,7 +43,6 @@ use crate::{bail_parse_error, Connection, Result, SymbolTable};
|
|||
use alter::translate_alter_table;
|
||||
use index::{translate_create_index, translate_drop_index};
|
||||
use insert::translate_insert;
|
||||
use limbo_sqlite3_parser::ast::{self, Delete, Insert};
|
||||
use rollback::translate_rollback;
|
||||
use schema::{translate_create_table, translate_create_virtual_table, translate_drop_table};
|
||||
use select::translate_select;
|
||||
|
@ -51,6 +50,7 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
use tracing::{instrument, Level};
|
||||
use transaction::{translate_tx_begin, translate_tx_commit};
|
||||
use turso_sqlite3_parser::ast::{self, Delete, Insert};
|
||||
use update::translate_update;
|
||||
|
||||
#[instrument(skip_all, level = Level::TRACE)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use limbo_sqlite3_parser::ast::SortOrder;
|
||||
use turso_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
use crate::{
|
||||
schema::Index,
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
},
|
||||
Result,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{self, SortOrder, TableInternalId};
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder, TableInternalId};
|
||||
|
||||
use super::cost::ESTIMATED_HARDCODED_ROWS_PER_TABLE;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{cell::RefCell, collections::HashMap};
|
||||
|
||||
use limbo_sqlite3_parser::ast::TableInternalId;
|
||||
use turso_sqlite3_parser::ast::TableInternalId;
|
||||
|
||||
use crate::{
|
||||
translate::{
|
||||
|
@ -492,7 +492,7 @@ fn generate_join_bitmasks(table_number_max_exclusive: usize, how_many: usize) ->
|
|||
mod tests {
|
||||
use std::{cell::Cell, rc::Rc, sync::Arc};
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, Expr, Operator, SortOrder, TableInternalId};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, Operator, SortOrder, TableInternalId};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::cell::Cell;
|
||||
|
||||
use limbo_sqlite3_parser::ast::{Expr, Operator};
|
||||
use turso_sqlite3_parser::ast::{Expr, Operator};
|
||||
|
||||
use crate::{
|
||||
translate::{expr::unwrap_parens_owned, plan::WhereTerm},
|
||||
|
@ -191,7 +191,7 @@ fn rebuild_or_expr_from_list(mut operands: Vec<Expr>) -> Expr {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::translate::plan::WhereTerm;
|
||||
use limbo_sqlite3_parser::ast::{self, Expr, Literal, Operator, TableInternalId};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, Literal, Operator, TableInternalId};
|
||||
|
||||
#[test]
|
||||
fn test_lift_common_subexpressions() -> Result<()> {
|
||||
|
|
|
@ -6,11 +6,11 @@ use constraints::{
|
|||
use cost::Cost;
|
||||
use join::{compute_best_join_order, BestJoinOrderResult};
|
||||
use lift_common_subexpressions::lift_common_subexpressions_from_binary_or_terms;
|
||||
use limbo_sqlite3_parser::{
|
||||
use order::{compute_order_target, plan_satisfies_order_target, EliminatesSortBy};
|
||||
use turso_sqlite3_parser::{
|
||||
ast::{self, Expr, SortOrder},
|
||||
to_sql_string::ToSqlString as _,
|
||||
};
|
||||
use order::{compute_order_target, plan_satisfies_order_target, EliminatesSortBy};
|
||||
|
||||
use crate::{
|
||||
parameters::PARAM_PREFIX,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, SortOrder, TableInternalId};
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder, TableInternalId};
|
||||
|
||||
use crate::{
|
||||
translate::plan::{GroupBy, IterationDirection, JoinedTable},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, SortOrder};
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder};
|
||||
|
||||
use crate::{
|
||||
schema::{Column, PseudoTable},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use limbo_sqlite3_parser::ast::{self, SortOrder};
|
||||
use std::{cell::Cell, cmp::Ordering, rc::Rc, sync::Arc};
|
||||
use turso_ext::{ConstraintInfo, ConstraintOp};
|
||||
use turso_sqlite3_parser::ast::{self, SortOrder};
|
||||
|
||||
use crate::{
|
||||
function::AggFunc,
|
||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||
};
|
||||
use crate::{schema::Type, types::SeekOp, util::can_pushdown_predicate};
|
||||
|
||||
use limbo_sqlite3_parser::ast::TableInternalId;
|
||||
use turso_sqlite3_parser::ast::TableInternalId;
|
||||
|
||||
use super::{emitter::OperationMode, planner::determine_where_to_eval_term};
|
||||
|
||||
|
@ -479,15 +479,15 @@ impl SelectPlan {
|
|||
return false;
|
||||
}
|
||||
|
||||
let count = limbo_sqlite3_parser::ast::Expr::FunctionCall {
|
||||
name: limbo_sqlite3_parser::ast::Id("count".to_string()),
|
||||
let count = turso_sqlite3_parser::ast::Expr::FunctionCall {
|
||||
name: turso_sqlite3_parser::ast::Id("count".to_string()),
|
||||
distinctness: None,
|
||||
args: None,
|
||||
order_by: None,
|
||||
filter_over: None,
|
||||
};
|
||||
let count_star = limbo_sqlite3_parser::ast::Expr::FunctionCallStar {
|
||||
name: limbo_sqlite3_parser::ast::Id("count".to_string()),
|
||||
let count_star = turso_sqlite3_parser::ast::Expr::FunctionCallStar {
|
||||
name: turso_sqlite3_parser::ast::Id("count".to_string()),
|
||||
filter_over: None,
|
||||
};
|
||||
let result_col_expr = &self.result_columns.first().unwrap().expr;
|
||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
|||
vdbe::{builder::TableRefIdCounter, BranchOffset},
|
||||
Result,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{
|
||||
use turso_sqlite3_parser::ast::{
|
||||
self, Expr, FromClause, JoinType, Limit, Materialized, TableInternalId, UnaryOperator, With,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! VDBE bytecode generation for pragma statements.
|
||||
//! More info: https://www.sqlite.org/pragma.html.
|
||||
|
||||
use limbo_sqlite3_parser::ast::PragmaName;
|
||||
use limbo_sqlite3_parser::ast::{self, Expr};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use turso_sqlite3_parser::ast::PragmaName;
|
||||
use turso_sqlite3_parser::ast::{self, Expr};
|
||||
|
||||
use crate::schema::Schema;
|
||||
use crate::storage::pager::AutoVacuumMode;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_sqlite3_parser::ast::Name;
|
||||
use turso_sqlite3_parser::ast::Name;
|
||||
|
||||
use crate::{
|
||||
schema::Schema,
|
||||
|
|
|
@ -20,8 +20,8 @@ use crate::LimboError;
|
|||
use crate::SymbolTable;
|
||||
use crate::{bail_parse_error, Result};
|
||||
|
||||
use limbo_sqlite3_parser::ast::{fmt::ToTokens, CreateVirtualTable};
|
||||
use turso_ext::VTabKind;
|
||||
use turso_sqlite3_parser::ast::{fmt::ToTokens, CreateVirtualTable};
|
||||
|
||||
pub fn translate_create_table(
|
||||
query_mode: QueryMode,
|
||||
|
@ -341,7 +341,7 @@ fn check_automatic_pk_index_required(
|
|||
let col_names = unique_columns
|
||||
.iter()
|
||||
.map(|column| match &column.expr {
|
||||
limbo_sqlite3_parser::ast::Expr::Id(id) => {
|
||||
turso_sqlite3_parser::ast::Expr::Id(id) => {
|
||||
if !columns.iter().any(|(k, _)| k.0 == id.0) {
|
||||
bail_parse_error!("No such column: {}", id.0);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ use crate::vdbe::builder::{ProgramBuilderOpts, QueryMode, TableRefIdCounter};
|
|||
use crate::vdbe::insn::Insn;
|
||||
use crate::SymbolTable;
|
||||
use crate::{schema::Schema, vdbe::builder::ProgramBuilder, Result};
|
||||
use limbo_sqlite3_parser::ast::{self, CompoundSelect, SortOrder};
|
||||
use limbo_sqlite3_parser::ast::{ResultColumn, SelectInner};
|
||||
use turso_sqlite3_parser::ast::{self, CompoundSelect, SortOrder};
|
||||
use turso_sqlite3_parser::ast::{ResultColumn, SelectInner};
|
||||
|
||||
pub struct TranslateSelectResult {
|
||||
pub program: ProgramBuilder,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::translate::{ProgramBuilder, ProgramBuilderOpts};
|
||||
use crate::vdbe::insn::Insn;
|
||||
use crate::{QueryMode, Result};
|
||||
use limbo_sqlite3_parser::ast::{Name, TransactionType};
|
||||
use turso_sqlite3_parser::ast::{Name, TransactionType};
|
||||
|
||||
pub fn translate_tx_begin(
|
||||
tx_type: Option<TransactionType>,
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
vdbe::builder::{ProgramBuilder, ProgramBuilderOpts, QueryMode},
|
||||
SymbolTable,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{self, Expr, ResultColumn, SortOrder, Update};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, ResultColumn, SortOrder, Update};
|
||||
|
||||
use super::emitter::emit_program;
|
||||
use super::optimizer::optimize_plan;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use limbo_sqlite3_parser::ast::SortOrder;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::Deserialize;
|
||||
use turso_ext::{AggCtx, FinalizeFunction, StepFunction};
|
||||
use turso_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
use crate::error::LimboError;
|
||||
use crate::ext::{ExtValue, ExtValueType};
|
||||
|
|
16
core/util.rs
16
core/util.rs
|
@ -5,10 +5,10 @@ use crate::{
|
|||
types::{Value, ValueType},
|
||||
LimboError, OpenFlags, Result, Statement, StepResult, SymbolTable, IO,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::{
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
use turso_sqlite3_parser::ast::{
|
||||
self, CreateTableBody, Expr, FunctionTail, Literal, UnaryOperator,
|
||||
};
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
pub trait RoundToPrecision {
|
||||
fn round_to_precision(self, precision: i32) -> f64;
|
||||
|
@ -529,7 +529,7 @@ pub fn columns_from_create_table_body(body: &ast::CreateTableBody) -> crate::Res
|
|||
.constraints
|
||||
.iter()
|
||||
.find_map(|c| match &c.constraint {
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Default(val) => {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Default(val) => {
|
||||
Some(val.clone())
|
||||
}
|
||||
_ => None,
|
||||
|
@ -537,7 +537,7 @@ pub fn columns_from_create_table_body(body: &ast::CreateTableBody) -> crate::Res
|
|||
notnull: column_def.constraints.iter().any(|c| {
|
||||
matches!(
|
||||
c.constraint,
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::NotNull { .. }
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::NotNull { .. }
|
||||
)
|
||||
}),
|
||||
ty_str: column_def
|
||||
|
@ -548,14 +548,14 @@ pub fn columns_from_create_table_body(body: &ast::CreateTableBody) -> crate::Res
|
|||
primary_key: column_def.constraints.iter().any(|c| {
|
||||
matches!(
|
||||
c.constraint,
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::PrimaryKey { .. }
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::PrimaryKey { .. }
|
||||
)
|
||||
}),
|
||||
is_rowid_alias: false,
|
||||
unique: column_def.constraints.iter().any(|c| {
|
||||
matches!(
|
||||
c.constraint,
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Unique(..)
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Unique(..)
|
||||
)
|
||||
}),
|
||||
collation: column_def
|
||||
|
@ -567,7 +567,7 @@ pub fn columns_from_create_table_body(body: &ast::CreateTableBody) -> crate::Res
|
|||
// But in the future, when a user defines a collation sequence, creates a table with it,
|
||||
// then closes the db and opens it again. This may panic here if the collation seq is not registered
|
||||
// before reading the columns
|
||||
limbo_sqlite3_parser::ast::ColumnConstraint::Collate {
|
||||
turso_sqlite3_parser::ast::ColumnConstraint::Collate {
|
||||
collation_name,
|
||||
} => Some(CollationSeq::new(collation_name.0.as_str()).expect(
|
||||
"collation should have been set correctly in create table",
|
||||
|
@ -1063,7 +1063,7 @@ pub fn vtable_args(args: &[ast::Expr]) -> Vec<turso_ext::Value> {
|
|||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use limbo_sqlite3_parser::ast::{self, Expr, Id, Literal, Operator::*, Type};
|
||||
use turso_sqlite3_parser::ast::{self, Expr, Id, Literal, Operator::*, Type};
|
||||
|
||||
#[test]
|
||||
fn test_normalize_ident() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{cell::Cell, cmp::Ordering, rc::Rc, sync::Arc};
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, TableInternalId};
|
||||
use tracing::{instrument, Level};
|
||||
use turso_sqlite3_parser::ast::{self, TableInternalId};
|
||||
|
||||
use crate::{
|
||||
numeric::Numeric,
|
||||
|
|
|
@ -61,11 +61,11 @@ use super::{
|
|||
CommitState,
|
||||
};
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use limbo_sqlite3_parser::ast;
|
||||
use limbo_sqlite3_parser::ast::fmt::ToTokens;
|
||||
use limbo_sqlite3_parser::lexer::sql::Parser;
|
||||
use parking_lot::RwLock;
|
||||
use rand::thread_rng;
|
||||
use turso_sqlite3_parser::ast;
|
||||
use turso_sqlite3_parser::ast::fmt::ToTokens;
|
||||
use turso_sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
use super::{
|
||||
likeop::{construct_like_escape_arg, exec_glob, exec_like_with_escape},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_sqlite3_parser::ast::SortOrder;
|
||||
use turso_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
use crate::vdbe::{builder::CursorType, insn::RegisterOrLiteral};
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ use crate::{
|
|||
translate::collate::CollationSeq,
|
||||
Value,
|
||||
};
|
||||
use limbo_sqlite3_parser::ast::SortOrder;
|
||||
use turso_macros::Description;
|
||||
use turso_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
/// Flags provided to comparison instructions (e.g. Eq, Ne) which determine behavior related to NULL values.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_sqlite3_parser::ast::SortOrder;
|
||||
use turso_sqlite3_parser::ast::SortOrder;
|
||||
|
||||
use crate::{
|
||||
translate::collate::CollationSeq,
|
||||
|
|
|
@ -3,12 +3,12 @@ use crate::schema::Column;
|
|||
use crate::util::{columns_from_create_table_body, vtable_args};
|
||||
use crate::{Connection, LimboError, SymbolTable, Value};
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use limbo_sqlite3_parser::{ast, lexer::sql::Parser};
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use turso_ext::{ConstraintInfo, IndexInfo, OrderByInfo, ResultCode, VTabKind, VTabModuleImpl};
|
||||
use turso_sqlite3_parser::{ast, lexer::sql::Parser};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum VirtualTableType {
|
||||
|
|
40
fuzz/Cargo.lock
generated
40
fuzz/Cargo.lock
generated
|
@ -572,25 +572,6 @@ dependencies = [
|
|||
"turso_ext",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_time"
|
||||
version = "0.1.0-pre.2"
|
||||
|
@ -1137,7 +1118,6 @@ dependencies = [
|
|||
"libloading",
|
||||
"libm",
|
||||
"limbo_series",
|
||||
"limbo_sqlite3_parser",
|
||||
"limbo_time",
|
||||
"limbo_uuid",
|
||||
"miette",
|
||||
|
@ -1156,6 +1136,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"turso_ext",
|
||||
"turso_macros",
|
||||
"turso_sqlite3_parser",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
|
@ -1177,6 +1158,25 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "turso_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.10"
|
||||
|
|
40
perf/latency/limbo/Cargo.lock
generated
40
perf/latency/limbo/Cargo.lock
generated
|
@ -660,25 +660,6 @@ dependencies = [
|
|||
"turso_ext",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limbo_time"
|
||||
version = "0.1.0-pre.2"
|
||||
|
@ -1238,7 +1219,6 @@ dependencies = [
|
|||
"libloading",
|
||||
"libm",
|
||||
"limbo_series",
|
||||
"limbo_sqlite3_parser",
|
||||
"limbo_time",
|
||||
"limbo_uuid",
|
||||
"miette",
|
||||
|
@ -1257,6 +1237,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"turso_ext",
|
||||
"turso_macros",
|
||||
"turso_sqlite3_parser",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
|
@ -1278,6 +1259,25 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "turso_sqlite3_parser"
|
||||
version = "0.1.0-pre.2"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
"miette",
|
||||
"phf",
|
||||
"phf_codegen",
|
||||
"phf_shared",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"uncased",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.10"
|
||||
|
|
|
@ -11,6 +11,6 @@ cargo publish -p limbo_series
|
|||
cargo publish -p limbo_time
|
||||
cargo publish -p limbo_uuid
|
||||
cargo publish -p limbo_ipaddr
|
||||
cargo publish -p limbo_sqlite3_parser
|
||||
cargo publish -p turso_sqlite3_parser
|
||||
cargo publish -p turso_core
|
||||
cargo publish -p limbo
|
||||
|
|
|
@ -35,5 +35,5 @@ chrono = { version = "0.4.40", features = ["serde"] }
|
|||
tracing = "0.1.41"
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
anyhow.workspace = true
|
||||
limbo_sqlite3_parser = { workspace = true, features = ["serde"]}
|
||||
turso_sqlite3_parser = { workspace = true, features = ["serde"]}
|
||||
hex = "0.4.3"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_sqlite3_parser::ast::{
|
||||
use turso_sqlite3_parser::ast::{
|
||||
self, Expr, LikeOperator, Name, Operator, QualifiedName, Type, UnaryOperator,
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Contains code for generation for [ast::Expr::Binary] Predicate
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, Expr};
|
||||
use turso_sqlite3_parser::ast::{self, Expr};
|
||||
|
||||
use crate::{
|
||||
generation::{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use limbo_sqlite3_parser::ast::{self, Expr};
|
||||
use rand::{seq::SliceRandom as _, Rng};
|
||||
use turso_sqlite3_parser::ast::{self, Expr};
|
||||
|
||||
use crate::model::{
|
||||
query::predicate::Predicate,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//! TODO: for now just generating [ast::Literal], but want to also generate Columns and any
|
||||
//! arbitrary [ast::Expr]
|
||||
|
||||
use limbo_sqlite3_parser::ast::{self, Expr};
|
||||
use turso_sqlite3_parser::ast::{self, Expr};
|
||||
|
||||
use crate::{
|
||||
generation::{backtrack, pick, predicate::SimplePredicate, ArbitraryFromMaybe},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use limbo_sqlite3_parser::ast;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turso_core::LimboError;
|
||||
use turso_sqlite3_parser::ast;
|
||||
|
||||
use crate::{
|
||||
model::{
|
||||
|
|
|
@ -5,9 +5,9 @@ pub(crate) use create_index::CreateIndex;
|
|||
pub(crate) use delete::Delete;
|
||||
pub(crate) use drop::Drop;
|
||||
pub(crate) use insert::Insert;
|
||||
use limbo_sqlite3_parser::to_sql_string::ToSqlContext;
|
||||
pub(crate) use select::Select;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turso_sqlite3_parser::to_sql_string::ToSqlContext;
|
||||
use update::Update;
|
||||
|
||||
use crate::{model::table::SimValue, runner::env::SimulatorEnv};
|
||||
|
@ -94,13 +94,13 @@ struct EmptyContext;
|
|||
impl ToSqlContext for EmptyContext {
|
||||
fn get_column_name(
|
||||
&self,
|
||||
_table_id: limbo_sqlite3_parser::ast::TableInternalId,
|
||||
_table_id: turso_sqlite3_parser::ast::TableInternalId,
|
||||
_col_idx: usize,
|
||||
) -> &str {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn get_table_name(&self, _id: limbo_sqlite3_parser::ast::TableInternalId) -> &str {
|
||||
fn get_table_name(&self, _id: turso_sqlite3_parser::ast::TableInternalId) -> &str {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use limbo_sqlite3_parser::{ast, to_sql_string::ToSqlString};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turso_sqlite3_parser::{ast, to_sql_string::ToSqlString};
|
||||
|
||||
use crate::model::{
|
||||
query::EmptyContext,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::{fmt::Display, hash::Hash, ops::Deref};
|
||||
|
||||
use limbo_sqlite3_parser::ast;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use turso_core::{numeric::Numeric, types};
|
||||
use turso_sqlite3_parser::ast;
|
||||
|
||||
pub(crate) struct Name(pub(crate) String);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "limbo_sqlite3_parser"
|
||||
name = "turso_sqlite3_parser"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors = ["gwenn"]
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use limbo_sqlite3_parser::dialect::keyword_token;
|
||||
use test::Bencher;
|
||||
use turso_sqlite3_parser::dialect::keyword_token;
|
||||
|
||||
static VALUES: [&[u8]; 136] = [
|
||||
b"ABORT",
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::env;
|
|||
use std::fs::read;
|
||||
use std::panic;
|
||||
|
||||
use limbo_sqlite3_parser::lexer::sql::Parser;
|
||||
use turso_sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
/// Parse specified files and check all commands.
|
||||
fn main() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::env;
|
||||
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use limbo_sqlite3_parser::lexer::sql::Parser;
|
||||
use turso_sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
/// Parse args.
|
||||
// RUST_LOG=sqlite3Parser=debug
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::fs::read;
|
|||
use std::panic;
|
||||
|
||||
#[cfg(not(feature = "YYNOERRORRECOVERY"))]
|
||||
use limbo_sqlite3_parser::lexer::sql::Error;
|
||||
use limbo_sqlite3_parser::lexer::sql::Parser;
|
||||
use turso_sqlite3_parser::lexer::sql::Error;
|
||||
use turso_sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
/// Parse specified files and print all commands.
|
||||
fn main() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use limbo_sqlite3_parser::lexer::sql::{TokenType, Tokenizer};
|
||||
use limbo_sqlite3_parser::lexer::Scanner;
|
||||
use turso_sqlite3_parser::lexer::sql::{TokenType, Tokenizer};
|
||||
use turso_sqlite3_parser::lexer::Scanner;
|
||||
|
||||
use std::env;
|
||||
use std::fs::read;
|
||||
|
|
|
@ -5,7 +5,7 @@ authors = ["Dandandan <danielheres@gmail.com>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
limbo_sqlite3_parser = { path = "..", default-features = false, features = [
|
||||
turso_sqlite3_parser = { path = "..", default-features = false, features = [
|
||||
"YYNOERRORRECOVERY",
|
||||
"NDEBUG",
|
||||
] }
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use fallible_iterator::FallibleIterator;
|
||||
use limbo_sqlite3_parser::lexer::sql::Parser;
|
||||
use turso_sqlite3_parser::lexer::sql::Parser;
|
||||
|
||||
fn basic_queries(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("sqlparser-rs parsing benchmark");
|
||||
|
|
|
@ -304,8 +304,8 @@ impl Tokenizer {
|
|||
}
|
||||
|
||||
/// ```rust
|
||||
/// use limbo_sqlite3_parser::lexer::sql::Tokenizer;
|
||||
/// use limbo_sqlite3_parser::lexer::Scanner;
|
||||
/// use turso_sqlite3_parser::lexer::sql::Tokenizer;
|
||||
/// use turso_sqlite3_parser::lexer::Scanner;
|
||||
///
|
||||
/// let tokenizer = Tokenizer::new();
|
||||
/// let input = b"PRAGMA parser_trace=ON;";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue