Merge 'Pagecount' from Glauber Costa

This PR implements the Pagecount pragma, as well as its associated
bytecode opcode

Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #819
This commit is contained in:
Pekka Enberg
2025-02-02 09:32:18 +02:00
7 changed files with 52 additions and 2 deletions

View File

@@ -135,7 +135,7 @@ The current status of Limbo is:
| PRAGMA mmap_size | No | |
| PRAGMA module_list | No | |
| PRAGMA optimize | No | |
| PRAGMA page_count | No | |
| PRAGMA page_count | Yes | |
| PRAGMA page_size | No | |
| PRAGMA parser_trace | No | |
| PRAGMA pragma_list | Yes | |
@@ -504,7 +504,7 @@ Modifiers:
| OpenWriteAsync | Yes | |
| OpenWriteAwait | Yes | |
| Or | Yes | |
| Pagecount | No | |
| Pagecount | Partial| no temp databases |
| Param | No | |
| ParseSchema | No | |
| Permutation | No | |

View File

@@ -640,6 +640,10 @@ fn update_pragma(
query_pragma(PragmaName::WalCheckpoint, schema, None, header, program)?;
Ok(())
}
PragmaName::PageCount => {
query_pragma(PragmaName::PageCount, schema, None, header, program)?;
Ok(())
}
PragmaName::TableInfo => {
// because we need control over the write parameter for the transaction,
// this should be unreachable. We have to force-call query_pragma before
@@ -681,6 +685,13 @@ fn query_pragma(
});
program.emit_result_row(register, 3);
}
PragmaName::PageCount => {
program.emit_insn(Insn::PageCount {
db: 0,
dest: register,
});
program.emit_result_row(register, 1);
}
PragmaName::TableInfo => {
let table = match value {
Some(ast::Expr::Name(name)) => {

View File

@@ -1163,6 +1163,15 @@ pub fn insn_to_str(
0,
String::new(),
),
Insn::PageCount { db, dest } => (
"Pagecount",
*db as i32,
*dest as i32,
0,
OwnedValue::build_text(Rc::new("".to_string())),
0,
"".to_string(),
),
};
format!(
"{:<4} {:<17} {:<4} {:<4} {:<4} {:<13} {:<2} {}",

View File

@@ -605,6 +605,11 @@ pub enum Insn {
dest: usize,
},
Noop,
/// Write the current number of pages in database P1 to memory cell P2.
PageCount {
db: usize,
dest: usize,
},
}
fn cast_text_to_numerical(value: &str) -> OwnedValue {

View File

@@ -2406,6 +2406,20 @@ impl Program {
state.pc += 1;
}
}
Insn::PageCount { db, dest } => {
if *db > 0 {
// TODO: implement temp databases
todo!("temp databases not implemented yet");
}
// SQLite returns "0" on an empty database, and 2 on the first insertion,
// so we'll mimick that behavior.
let mut pages = pager.db_header.borrow().database_size.into();
if pages == 1 {
pages = 0;
}
state.registers[*dest] = OwnedValue::Integer(pages);
state.pc += 1;
}
Insn::ParseSchema {
db: _,
where_clause,

View File

@@ -32,3 +32,12 @@ do_execsql_test pragma-table-info-call-syntax {
do_execsql_test pragma-table-info-invalid-table {
PRAGMA table_info=pekka
} {}
do_execsql_test_on_specific_db ":memory:" pragma-page-count-empty {
PRAGMA page_count
} {0}
do_execsql_test_on_specific_db ":memory:" pragma-page-count-table {
CREATE TABLE foo(bar);
PRAGMA page_count
} {2}

View File

@@ -1594,6 +1594,8 @@ pub enum PragmaName {
CacheSize,
/// `journal_mode` pragma
JournalMode,
/// Return the total number of pages in the database file.
PageCount,
/// returns information about the columns of a table
TableInfo,
/// trigger a checkpoint to run on database(s) if WAL is enabled