mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-31 05:44:25 +01:00
Merge 'Add support for default values in INSERT statements' from Diego Reis
While working on #494 I noticed that default values defined in schemas weren't being applied. Before:  Now:  Closes #1249
This commit is contained in:
@@ -297,6 +297,8 @@ struct ColumnMapping<'a> {
|
||||
/// If Some(i), use the i-th value from the VALUES tuple
|
||||
/// If None, use NULL (column was not specified in INSERT statement)
|
||||
value_index: Option<usize>,
|
||||
/// The default value for the column, if defined
|
||||
default_value: Option<&'a Expr>,
|
||||
}
|
||||
|
||||
/// Resolves how each column in a table should be populated during an INSERT.
|
||||
@@ -352,6 +354,7 @@ fn resolve_columns_for_insert<'a>(
|
||||
.map(|(i, col)| ColumnMapping {
|
||||
column: col,
|
||||
value_index: if i < num_values { Some(i) } else { None },
|
||||
default_value: col.default.as_ref(),
|
||||
})
|
||||
.collect());
|
||||
}
|
||||
@@ -362,6 +365,7 @@ fn resolve_columns_for_insert<'a>(
|
||||
.map(|col| ColumnMapping {
|
||||
column: col,
|
||||
value_index: None,
|
||||
default_value: col.default.as_ref(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -423,8 +427,10 @@ fn populate_column_registers(
|
||||
if write_directly_to_rowid_reg {
|
||||
program.emit_insn(Insn::SoftNull { reg: target_reg });
|
||||
}
|
||||
} else if let Some(default_expr) = mapping.default_value {
|
||||
translate_expr(program, None, default_expr, target_reg, resolver)?;
|
||||
} else {
|
||||
// Column was not specified - use NULL if it is nullable, otherwise error
|
||||
// Column was not specified as has no DEFAULT - use NULL if it is nullable, otherwise error
|
||||
// Rowid alias columns can be NULL because we will autogenerate a rowid in that case.
|
||||
let is_nullable = !mapping.column.primary_key || mapping.column.is_rowid_alias;
|
||||
if is_nullable {
|
||||
|
||||
@@ -40,102 +40,102 @@ impl CmpInsFlags {
|
||||
|
||||
#[derive(Description, Debug)]
|
||||
pub enum Insn {
|
||||
// Initialize the program state and jump to the given PC.
|
||||
/// Initialize the program state and jump to the given PC.
|
||||
Init {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
// Write a NULL into register dest. If dest_end is Some, then also write NULL into register dest_end and every register in between dest and dest_end. If dest_end is not set, then only register dest is set to NULL.
|
||||
/// Write a NULL into register dest. If dest_end is Some, then also write NULL into register dest_end and every register in between dest and dest_end. If dest_end is not set, then only register dest is set to NULL.
|
||||
Null {
|
||||
dest: usize,
|
||||
dest_end: Option<usize>,
|
||||
},
|
||||
// Move the cursor P1 to a null row. Any Column operations that occur while the cursor is on the null row will always write a NULL.
|
||||
/// Move the cursor P1 to a null row. Any Column operations that occur while the cursor is on the null row will always write a NULL.
|
||||
NullRow {
|
||||
cursor_id: CursorID,
|
||||
},
|
||||
// Add two registers and store the result in a third register.
|
||||
/// Add two registers and store the result in a third register.
|
||||
Add {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Subtract rhs from lhs and store in dest
|
||||
/// Subtract rhs from lhs and store in dest
|
||||
Subtract {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Multiply two registers and store the result in a third register.
|
||||
/// Multiply two registers and store the result in a third register.
|
||||
Multiply {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Divide lhs by rhs and store the result in a third register.
|
||||
/// Divide lhs by rhs and store the result in a third register.
|
||||
Divide {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of the comparison for use by the next Jump instruct.
|
||||
/// Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of the comparison for use by the next Jump instruct.
|
||||
Compare {
|
||||
start_reg_a: usize,
|
||||
start_reg_b: usize,
|
||||
count: usize,
|
||||
},
|
||||
// Place the result of rhs bitwise AND lhs in third register.
|
||||
/// Place the result of rhs bitwise AND lhs in third register.
|
||||
BitAnd {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Place the result of rhs bitwise OR lhs in third register.
|
||||
/// Place the result of rhs bitwise OR lhs in third register.
|
||||
BitOr {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Place the result of bitwise NOT register P1 in dest register.
|
||||
/// Place the result of bitwise NOT register P1 in dest register.
|
||||
BitNot {
|
||||
reg: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Checkpoint the database (applying wal file content to database file).
|
||||
/// Checkpoint the database (applying wal file content to database file).
|
||||
Checkpoint {
|
||||
database: usize, // checkpoint database P1
|
||||
checkpoint_mode: CheckpointMode, // P2 checkpoint mode
|
||||
dest: usize, // P3 checkpoint result
|
||||
},
|
||||
// Divide lhs by rhs and place the remainder in dest register.
|
||||
/// Divide lhs by rhs and place the remainder in dest register.
|
||||
Remainder {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
// Jump to the instruction at address P1, P2, or P3 depending on whether in the most recent Compare instruction the P1 vector was less than, equal to, or greater than the P2 vector, respectively.
|
||||
/// Jump to the instruction at address P1, P2, or P3 depending on whether in the most recent Compare instruction the P1 vector was less than, equal to, or greater than the P2 vector, respectively.
|
||||
Jump {
|
||||
target_pc_lt: BranchOffset,
|
||||
target_pc_eq: BranchOffset,
|
||||
target_pc_gt: BranchOffset,
|
||||
},
|
||||
// Move the P3 values in register P1..P1+P3-1 over into registers P2..P2+P3-1. Registers P1..P1+P3-1 are left holding a NULL. It is an error for register ranges P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error for P3 to be less than 1.
|
||||
/// Move the P3 values in register P1..P1+P3-1 over into registers P2..P2+P3-1. Registers P1..P1+P3-1 are left holding a NULL. It is an error for register ranges P1..P1+P3-1 and P2..P2+P3-1 to overlap. It is an error for P3 to be less than 1.
|
||||
Move {
|
||||
source_reg: usize,
|
||||
dest_reg: usize,
|
||||
count: usize,
|
||||
},
|
||||
// If the given register is a positive integer, decrement it by decrement_by and jump to the given PC.
|
||||
/// If the given register is a positive integer, decrement it by decrement_by and jump to the given PC.
|
||||
IfPos {
|
||||
reg: usize,
|
||||
target_pc: BranchOffset,
|
||||
decrement_by: usize,
|
||||
},
|
||||
// If the given register is not NULL, jump to the given PC.
|
||||
/// If the given register is not NULL, jump to the given PC.
|
||||
NotNull {
|
||||
reg: usize,
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
// Compare two registers and jump to the given PC if they are equal.
|
||||
/// Compare two registers and jump to the given PC if they are equal.
|
||||
Eq {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -149,7 +149,7 @@ pub enum Insn {
|
||||
/// This flag indicates that if either is null we should still jump.
|
||||
flags: CmpInsFlags,
|
||||
},
|
||||
// Compare two registers and jump to the given PC if they are not equal.
|
||||
/// Compare two registers and jump to the given PC if they are not equal.
|
||||
Ne {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -159,7 +159,7 @@ pub enum Insn {
|
||||
/// jump_if_null jumps if either of the operands is null. Used for "jump when false" logic.
|
||||
flags: CmpInsFlags,
|
||||
},
|
||||
// Compare two registers and jump to the given PC if the left-hand side is less than the right-hand side.
|
||||
/// Compare two registers and jump to the given PC if the left-hand side is less than the right-hand side.
|
||||
Lt {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -175,7 +175,7 @@ pub enum Insn {
|
||||
/// jump_if_null: Jump if either of the operands is null. Used for "jump when false" logic.
|
||||
flags: CmpInsFlags,
|
||||
},
|
||||
// Compare two registers and jump to the given PC if the left-hand side is greater than the right-hand side.
|
||||
/// Compare two registers and jump to the given PC if the left-hand side is greater than the right-hand side.
|
||||
Gt {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -183,7 +183,7 @@ pub enum Insn {
|
||||
/// jump_if_null: Jump if either of the operands is null. Used for "jump when false" logic.
|
||||
flags: CmpInsFlags,
|
||||
},
|
||||
// Compare two registers and jump to the given PC if the left-hand side is greater than or equal to the right-hand side.
|
||||
/// Compare two registers and jump to the given PC if the left-hand side is greater than or equal to the right-hand side.
|
||||
Ge {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -205,13 +205,13 @@ pub enum Insn {
|
||||
/// P3. If r\[reg\] is null, jump iff r\[jump_if_null\] != 0
|
||||
jump_if_null: bool,
|
||||
},
|
||||
// Open a cursor for reading.
|
||||
/// Open a cursor for reading.
|
||||
OpenReadAsync {
|
||||
cursor_id: CursorID,
|
||||
root_page: PageIdx,
|
||||
},
|
||||
|
||||
// Await for the completion of open cursor.
|
||||
/// Await for the completion of open cursor.
|
||||
OpenReadAwait,
|
||||
|
||||
/// Open a cursor for a virtual table.
|
||||
@@ -260,19 +260,19 @@ pub enum Insn {
|
||||
pc_if_next: BranchOffset,
|
||||
},
|
||||
|
||||
// Open a cursor for a pseudo-table that contains a single row.
|
||||
/// Open a cursor for a pseudo-table that contains a single row.
|
||||
OpenPseudo {
|
||||
cursor_id: CursorID,
|
||||
content_reg: usize,
|
||||
num_fields: usize,
|
||||
},
|
||||
|
||||
// Rewind the cursor to the beginning of the B-Tree.
|
||||
/// Rewind the cursor to the beginning of the B-Tree.
|
||||
RewindAsync {
|
||||
cursor_id: CursorID,
|
||||
},
|
||||
|
||||
// Await for the completion of cursor rewind.
|
||||
/// Await for the completion of cursor rewind.
|
||||
RewindAwait {
|
||||
cursor_id: CursorID,
|
||||
pc_if_empty: BranchOffset,
|
||||
@@ -287,32 +287,32 @@ pub enum Insn {
|
||||
pc_if_empty: BranchOffset,
|
||||
},
|
||||
|
||||
// Read a column from the current row of the cursor.
|
||||
/// Read a column from the current row of the cursor.
|
||||
Column {
|
||||
cursor_id: CursorID,
|
||||
column: usize,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Make a record and write it to destination register.
|
||||
/// Make a record and write it to destination register.
|
||||
MakeRecord {
|
||||
start_reg: usize, // P1
|
||||
count: usize, // P2
|
||||
dest_reg: usize, // P3
|
||||
},
|
||||
|
||||
// Emit a row of results.
|
||||
/// Emit a row of results.
|
||||
ResultRow {
|
||||
start_reg: usize, // P1
|
||||
count: usize, // P2
|
||||
},
|
||||
|
||||
// Advance the cursor to the next row.
|
||||
/// Advance the cursor to the next row.
|
||||
NextAsync {
|
||||
cursor_id: CursorID,
|
||||
},
|
||||
|
||||
// Await for the completion of cursor advance.
|
||||
/// Await for the completion of cursor advance.
|
||||
NextAwait {
|
||||
cursor_id: CursorID,
|
||||
pc_if_next: BranchOffset,
|
||||
@@ -327,91 +327,91 @@ pub enum Insn {
|
||||
pc_if_next: BranchOffset,
|
||||
},
|
||||
|
||||
// Halt the program.
|
||||
/// Halt the program.
|
||||
Halt {
|
||||
err_code: usize,
|
||||
description: String,
|
||||
},
|
||||
|
||||
// Start a transaction.
|
||||
/// Start a transaction.
|
||||
Transaction {
|
||||
write: bool,
|
||||
},
|
||||
|
||||
// Set database auto-commit mode and potentially rollback.
|
||||
/// Set database auto-commit mode and potentially rollback.
|
||||
AutoCommit {
|
||||
auto_commit: bool,
|
||||
rollback: bool,
|
||||
},
|
||||
|
||||
// Branch to the given PC.
|
||||
/// Branch to the given PC.
|
||||
Goto {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// Stores the current program counter into register 'return_reg' then jumps to address target_pc.
|
||||
/// Stores the current program counter into register 'return_reg' then jumps to address target_pc.
|
||||
Gosub {
|
||||
target_pc: BranchOffset,
|
||||
return_reg: usize,
|
||||
},
|
||||
|
||||
// Returns to the program counter stored in register 'return_reg'.
|
||||
/// Returns to the program counter stored in register 'return_reg'.
|
||||
Return {
|
||||
return_reg: usize,
|
||||
},
|
||||
|
||||
// Write an integer value into a register.
|
||||
/// Write an integer value into a register.
|
||||
Integer {
|
||||
value: i64,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Write a float value into a register
|
||||
/// Write a float value into a register
|
||||
Real {
|
||||
value: f64,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// If register holds an integer, transform it to a float
|
||||
/// If register holds an integer, transform it to a float
|
||||
RealAffinity {
|
||||
register: usize,
|
||||
},
|
||||
|
||||
// Write a string value into a register.
|
||||
/// Write a string value into a register.
|
||||
String8 {
|
||||
value: String,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Write a blob value into a register.
|
||||
/// Write a blob value into a register.
|
||||
Blob {
|
||||
value: Vec<u8>,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Read the rowid of the current row.
|
||||
/// Read the rowid of the current row.
|
||||
RowId {
|
||||
cursor_id: CursorID,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Seek to a rowid in the cursor. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
/// Seek to a rowid in the cursor. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
SeekRowid {
|
||||
cursor_id: CursorID,
|
||||
src_reg: usize,
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// P1 is an open index cursor and P3 is a cursor on the corresponding table. This opcode does a deferred seek of the P3 table cursor to the row that corresponds to the current row of P1.
|
||||
// This is a deferred seek. Nothing actually happens until the cursor is used to read a record. That way, if no reads occur, no unnecessary I/O happens.
|
||||
/// P1 is an open index cursor and P3 is a cursor on the corresponding table. This opcode does a deferred seek of the P3 table cursor to the row that corresponds to the current row of P1.
|
||||
/// This is a deferred seek. Nothing actually happens until the cursor is used to read a record. That way, if no reads occur, no unnecessary I/O happens.
|
||||
DeferredSeek {
|
||||
index_cursor_id: CursorID,
|
||||
table_cursor_id: CursorID,
|
||||
},
|
||||
|
||||
// If cursor_id refers to an SQL table (B-Tree that uses integer keys), use the value in start_reg as the key.
|
||||
// If cursor_id refers to an SQL index, then start_reg is the first in an array of num_regs registers that are used as an unpacked index key.
|
||||
// Seek to the first index entry that is greater than or equal to the given key. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
/// If cursor_id refers to an SQL table (B-Tree that uses integer keys), use the value in start_reg as the key.
|
||||
/// If cursor_id refers to an SQL index, then start_reg is the first in an array of num_regs registers that are used as an unpacked index key.
|
||||
/// Seek to the first index entry that is greater than or equal to the given key. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
SeekGE {
|
||||
is_index: bool,
|
||||
cursor_id: CursorID,
|
||||
@@ -420,9 +420,9 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// If cursor_id refers to an SQL table (B-Tree that uses integer keys), use the value in start_reg as the key.
|
||||
// If cursor_id refers to an SQL index, then start_reg is the first in an array of num_regs registers that are used as an unpacked index key.
|
||||
// Seek to the first index entry that is greater than the given key. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
/// If cursor_id refers to an SQL table (B-Tree that uses integer keys), use the value in start_reg as the key.
|
||||
/// If cursor_id refers to an SQL index, then start_reg is the first in an array of num_regs registers that are used as an unpacked index key.
|
||||
/// Seek to the first index entry that is greater than the given key. If not found, jump to the given PC. Otherwise, continue to the next instruction.
|
||||
SeekGT {
|
||||
is_index: bool,
|
||||
cursor_id: CursorID,
|
||||
@@ -431,8 +431,8 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
// If the P1 index entry is greater or equal than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
/// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
/// If the P1 index entry is greater or equal than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
IdxGE {
|
||||
cursor_id: CursorID,
|
||||
start_reg: usize,
|
||||
@@ -440,8 +440,8 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
// If the P1 index entry is greater than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
/// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
/// If the P1 index entry is greater than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
IdxGT {
|
||||
cursor_id: CursorID,
|
||||
start_reg: usize,
|
||||
@@ -449,8 +449,8 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
// If the P1 index entry is lesser or equal than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
/// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
/// If the P1 index entry is lesser or equal than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
IdxLE {
|
||||
cursor_id: CursorID,
|
||||
start_reg: usize,
|
||||
@@ -458,8 +458,8 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
// If the P1 index entry is lesser than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
/// The P4 register values beginning with P3 form an unpacked index key that omits the PRIMARY KEY. Compare this key value against the index that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID fields at the end.
|
||||
/// If the P1 index entry is lesser than the key value then jump to P2. Otherwise fall through to the next instruction.
|
||||
IdxLT {
|
||||
cursor_id: CursorID,
|
||||
start_reg: usize,
|
||||
@@ -467,7 +467,7 @@ pub enum Insn {
|
||||
target_pc: BranchOffset,
|
||||
},
|
||||
|
||||
// Decrement the given register and jump to the given PC if the result is zero.
|
||||
/// Decrement the given register and jump to the given PC if the result is zero.
|
||||
DecrJumpZero {
|
||||
reg: usize,
|
||||
target_pc: BranchOffset,
|
||||
@@ -485,39 +485,39 @@ pub enum Insn {
|
||||
func: AggFunc,
|
||||
},
|
||||
|
||||
// Open a sorter.
|
||||
/// Open a sorter.
|
||||
SorterOpen {
|
||||
cursor_id: CursorID, // P1
|
||||
columns: usize, // P2
|
||||
order: Record, // P4. 0 if ASC and 1 if DESC
|
||||
},
|
||||
|
||||
// Insert a row into the sorter.
|
||||
/// Insert a row into the sorter.
|
||||
SorterInsert {
|
||||
cursor_id: CursorID,
|
||||
record_reg: usize,
|
||||
},
|
||||
|
||||
// Sort the rows in the sorter.
|
||||
/// Sort the rows in the sorter.
|
||||
SorterSort {
|
||||
cursor_id: CursorID,
|
||||
pc_if_empty: BranchOffset,
|
||||
},
|
||||
|
||||
// Retrieve the next row from the sorter.
|
||||
/// Retrieve the next row from the sorter.
|
||||
SorterData {
|
||||
cursor_id: CursorID, // P1
|
||||
dest_reg: usize, // P2
|
||||
pseudo_cursor: usize, // P3
|
||||
},
|
||||
|
||||
// Advance to the next row in the sorter.
|
||||
/// Advance to the next row in the sorter.
|
||||
SorterNext {
|
||||
cursor_id: CursorID,
|
||||
pc_if_next: BranchOffset,
|
||||
},
|
||||
|
||||
// Function
|
||||
/// Function
|
||||
Function {
|
||||
constant_mask: i32, // P1
|
||||
start_reg: usize, // P2, start of argument registers
|
||||
@@ -618,7 +618,7 @@ pub enum Insn {
|
||||
is_temp: usize,
|
||||
},
|
||||
|
||||
// Drop a table
|
||||
/// Drop a table
|
||||
DropTable {
|
||||
/// The database within which this b-tree needs to be dropped (P1).
|
||||
db: usize,
|
||||
@@ -648,14 +648,14 @@ pub enum Insn {
|
||||
where_clause: String,
|
||||
},
|
||||
|
||||
// Place the result of lhs >> rhs in dest register.
|
||||
/// Place the result of lhs >> rhs in dest register.
|
||||
ShiftRight {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
|
||||
// Place the result of lhs << rhs in dest register.
|
||||
/// Place the result of lhs << rhs in dest register.
|
||||
ShiftLeft {
|
||||
lhs: usize,
|
||||
rhs: usize,
|
||||
@@ -697,6 +697,7 @@ pub enum Insn {
|
||||
rhs: usize,
|
||||
dest: usize,
|
||||
},
|
||||
/// Do nothing. Continue downward to the next opcode.
|
||||
Noop,
|
||||
/// Write the current number of pages in database P1 to memory cell P2.
|
||||
PageCount {
|
||||
|
||||
@@ -28,3 +28,4 @@ source $testdir/scalar-functions-printf.test
|
||||
source $testdir/transactions.test
|
||||
source $testdir/update.test
|
||||
source $testdir/drop_table.test
|
||||
source $testdir/default_value.test
|
||||
|
||||
43
testing/default_value.test
Normal file
43
testing/default_value.test
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env tclsh
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-text {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT DEFAULT 'default_value');
|
||||
INSERT INTO t1 (x) VALUES (1);
|
||||
SELECT y FROM t1 WHERE x = 1;
|
||||
} {default_value}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-integer {
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY, y INTEGER DEFAULT 42);
|
||||
INSERT INTO t2 (x) VALUES (1);
|
||||
SELECT y FROM t2 WHERE x = 1;
|
||||
} {42}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-real {
|
||||
CREATE TABLE t3(x INTEGER PRIMARY KEY, y REAL DEFAULT 3.14);
|
||||
INSERT INTO t3 (x) VALUES (1);
|
||||
SELECT y FROM t3 WHERE x = 1;
|
||||
} {3.14}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-null {
|
||||
CREATE TABLE t5(x INTEGER PRIMARY KEY, y TEXT DEFAULT NULL);
|
||||
INSERT INTO t5 (x) VALUES (1);
|
||||
SELECT y FROM t5 WHERE x = 1;
|
||||
} {}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-boolean {
|
||||
CREATE TABLE t6(x INTEGER PRIMARY KEY, y BOOLEAN DEFAULT 1);
|
||||
INSERT INTO t6 (x) VALUES (1);
|
||||
SELECT y FROM t6 WHERE x = 1;
|
||||
} {1}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} default-value-function {
|
||||
CREATE TABLE t7(x INTEGER PRIMARY KEY, y INTEGER DEFAULT (ABS(-5)));
|
||||
INSERT INTO t7 (x) VALUES (1);
|
||||
SELECT y FROM t7 WHERE x = 1;
|
||||
} {5}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user