1#![cfg_attr(
93 any(debug_assertions, not(feature = "unsafe-optim")),
94 forbid(unsafe_code)
95)] #![deny(missing_docs)]
97
98pub use crate::{
99 blockpagestg::BlockPageStg,
100 builtin::standard_builtins,
101 pstore::{AccessPagedData, SharedPagedData},
102 stg::{PageStorage, PageStorageInfo, SimpleFileStorage},
103};
104pub use atom_file::{AtomicFile, BasicAtomicFile, DummyFile, MemFile, MultiFileStorage, Storage};
105
106#[cfg(feature = "gentrans")]
107pub use crate::gentrans::{GenQuery, GenTransaction, Part};
108
109#[cfg(feature = "builtin")]
110pub use crate::{
111 builtin::check_types,
112 compile::{c_bool, c_float, c_int, c_value},
113 exec::EvalEnv,
114 expr::ObjRef,
115 expr::{Block, DataKind, Expr},
116 run::{CExp, CExpPtr, CompileFunc},
117 value::Value,
118};
119#[cfg(not(feature = "builtin"))]
120use crate::{
121 compile::{c_bool, c_int, c_value},
122 exec::EvalEnv,
123 expr::{Block, DataKind, Expr},
124 run::{CExp, CExpPtr, CompileFunc},
125 value::Value,
126};
127
128use crate::{
129 bytes::ByteStorage,
130 expr::*,
131 page::{Page, PagePtr},
132 parse::Parser,
133 run::*,
134 sortedfile::{Asc, Id, Record, SortedFile},
135 table::{ColInfo, IndexInfo, Row, SaveOp, Table},
136 util::{SmallSet, nd, newmap},
137 value::*,
138};
139
140#[cfg(feature = "pstd")]
141pub use pstd::collections::BTreeMap;
142
143#[cfg(not(feature = "pstd"))]
144pub use std::collections::BTreeMap;
145
146use std::{
147 any::Any,
148 cell::{Cell, RefCell},
149 cmp::Ordering,
150 collections::BTreeSet,
151 panic,
152 rc::Rc,
153 sync::{Arc, Mutex, RwLock},
154};
155
156use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
158
159#[cfg(feature = "max")]
161#[macro_use]
162pub mod util;
163#[cfg(not(feature = "max"))]
164#[macro_use]
165mod util;
166
167#[cfg(feature = "gentrans")]
168pub mod gentrans;
170
171pub mod stg;
173
174pub mod block;
176
177pub mod dividedstg;
179
180pub mod blockpagestg;
182
183pub mod pstore;
185
186pub mod test;
188
189pub mod bench;
191
192#[cfg(feature = "builtin")]
200pub mod builtin;
202#[cfg(not(feature = "builtin"))]
203mod builtin;
204
205#[cfg(feature = "builtin")]
206pub mod compile;
208#[cfg(not(feature = "builtin"))]
209mod compile;
210
211#[cfg(feature = "builtin")]
212pub mod expr;
214#[cfg(not(feature = "builtin"))]
215mod expr;
216
217#[cfg(feature = "table")]
218pub mod sortedfile;
220#[cfg(not(feature = "table"))]
221mod sortedfile;
222
223#[cfg(feature = "table")]
224pub mod table;
226#[cfg(not(feature = "table"))]
227mod table;
228
229#[cfg(feature = "table")]
230pub mod page;
232#[cfg(not(feature = "table"))]
233mod page;
234
235#[cfg(feature = "builtin")]
236pub mod value;
238#[cfg(not(feature = "builtin"))]
239mod value;
240
241#[cfg(feature = "max")]
242pub mod exec;
244#[cfg(not(feature = "max"))]
245mod exec;
246
247pub mod compact;
249
250#[cfg(feature = "max")]
251pub mod sys;
253#[cfg(not(feature = "max"))]
254mod sys;
255
256#[cfg(feature = "max")]
257pub mod parse;
259#[cfg(not(feature = "max"))]
260mod parse;
261
262#[cfg(feature = "max")]
263pub mod run;
265#[cfg(not(feature = "max"))]
266mod run;
267
268#[cfg(feature = "max")]
269pub mod cexp;
271#[cfg(not(feature = "max"))]
272mod cexp;
273
274#[cfg(feature = "max")]
275pub mod heap;
277#[cfg(not(feature = "max"))]
278mod heap;
279
280#[cfg(feature = "max")]
281pub mod bytes;
283#[cfg(not(feature = "max"))]
284mod bytes;
285
286pub type Data = Arc<Vec<u8>>;
290
291pub struct MData(Data);
293
294impl MData {
295 pub fn new(data: Data) -> MData {
297 MData(data)
298 }
299 pub fn to_data(&mut self) -> Data {
301 self.0.clone()
302 }
303}
304
305impl std::ops::Deref for MData {
306 type Target = Vec<u8>;
307 fn deref(&self) -> &Self::Target {
308 &self.0
309 }
310}
311
312impl std::ops::DerefMut for MData {
313 fn deref_mut(&mut self) -> &mut Self::Target {
314 Arc::make_mut(&mut self.0)
315 }
316}
317
318pub type DB = Rc<Database>;
320
321pub type BuiltinMap = HashMap<String, (DataKind, CompileFunc)>;
323
324pub struct Database {
326 pub apd: AccessPagedData,
328
329 pub builtins: Arc<BuiltinMap>,
331
332 pub sys_schema: Rc<Table>,
335 pub sys_table: Rc<Table>,
337 pub sys_column: Rc<Table>,
339 pub sys_index: Rc<Table>,
341 pub sys_index_col: Rc<Table>,
343 pub sys_function: Rc<Table>,
345
346 pub schemas: RefCell<HashMap<String, i64>>,
348 pub tables: RefCell<HashMap<ObjRef, Rc<Table>>>,
350 pub functions: RefCell<HashMap<ObjRef, Rc<Function>>>,
352
353 pub lastid: Cell<i64>,
355 pub err: Cell<bool>,
357 pub is_new: bool,
359
360 bs: Vec<ByteStorage>,
362 pub function_reset: Cell<bool>,
364 page_size_max: usize,
366
367 bpf: [usize; bytes::NFT],
368}
369
370const SYS_ROOT_LAST: u64 = 16;
371
372impl Database {
373 pub fn new(apd: AccessPagedData, initsql: &str, builtins: Arc<BuiltinMap>) -> DB {
377 let is_new = apd.is_new();
378 let mut tb = TableBuilder::new();
379 let sys_schema = tb.nt("Schema", &[("Name", STRING)]);
380 let sys_table = tb.nt(
381 "Table",
382 &[
383 ("Root", INT),
384 ("Schema", INT),
385 ("Name", STRING),
386 ("IdGen", INT),
387 ],
388 );
389 let sys_column = tb.nt("Column", &[("Table", INT), ("Name", STRING), ("Type", INT)]);
390 let sys_index = tb.nt("Index", &[("Root", INT), ("Table", INT), ("Name", STRING)]);
391 let sys_index_col = tb.nt("IndexColumn", &[("Index", INT), ("ColId", INT)]);
392 let sys_function = tb.nt(
393 "Function",
394 &[("Schema", INT), ("Name", NAMESTR), ("Def", BIGSTR)],
395 );
396 sys_schema.add_index(tb.rt(), vec![0], 1);
397 sys_table.add_index(tb.rt(), vec![1, 2], 2);
398 sys_column.add_index(tb.rt(), vec![0], 3);
399 sys_index.add_index(tb.rt(), vec![1], 4);
400 sys_index_col.add_index(tb.rt(), vec![0], 5);
401 sys_function.add_index(tb.rt(), vec![0, 1], 6);
402 sys_function.add_index(tb.rt(), vec![1], 7);
403
404 let page_size_max = apd.spd.psi.max_size_page();
405
406 let bpf = bytes::bpf(apd.spd.psi.half_size_page());
407
408 let mut bs = Vec::new();
409 for (ft, bpf) in bpf.iter().enumerate() {
410 bs.push(ByteStorage::new(ft as u64, *bpf));
411 }
412
413 let db = Rc::new(Database {
414 apd,
415 sys_schema,
416 sys_table,
417 sys_column,
418 sys_index,
419 sys_index_col,
420 sys_function,
421 bs,
422 schemas: newmap(),
423 functions: newmap(),
424 tables: newmap(),
425 builtins,
426 function_reset: Cell::new(false),
427 lastid: Cell::new(0),
428 err: Cell::new(false),
429 is_new,
430 page_size_max,
431 bpf,
432 });
433
434 assert!(tb.alloc as u64 - 1 == SYS_ROOT_LAST);
435
436 if is_new {
437 for _ft in 0..bytes::NFT {
438 db.alloc_page(); }
440 }
441 for t in &tb.list {
442 if !is_new {
443 t.id_gen.set(None);
444 }
445 db.publish_table(t.clone());
446 }
447
448 if is_new {
449 let sysinit = "
451CREATE SCHEMA sys
452GO
453CREATE TABLE sys.Schema( Name string )
454CREATE TABLE sys.Table( Root int, Schema int, Name string, IdGen int )
455CREATE TABLE sys.Column( Table int, Name string, Type int )
456CREATE TABLE sys.Index( Root int, Table int, Name string )
457CREATE TABLE sys.IndexColumn( Index int, ColId int )
458CREATE TABLE sys.Function( Schema int, Name string(31), Def string(249) )
459GO
460CREATE INDEX ByName ON sys.Schema(Name)
461CREATE INDEX BySchemaName ON sys.Table(Schema,Name)
462CREATE INDEX ByTable ON sys.Column(Table)
463CREATE INDEX ByTable ON sys.Index(Table)
464CREATE INDEX ByIndex ON sys.IndexColumn(Index)
465CREATE INDEX BySchemaName ON sys.Function(Schema,Name)
466CREATE INDEX ByName ON sys.Function(Name)
467GO
468";
469 let mut dq = DummyTransaction {};
470 db.run(sysinit, &mut dq);
471 db.run(initsql, &mut dq);
472 db.save();
473 }
474
475 db
476 }
477
478 pub fn run(self: &DB, source: &str, tr: &mut dyn Transaction) {
480 if let Some(e) = self.go(source, tr) {
481 let err = format!(
482 "{} in {} at line {} column {}.",
483 e.msg, e.rname, e.line, e.column
484 );
485 tr.set_error(err);
486 self.err.set(true);
487 }
488 }
489
490 fn go(self: &DB, source: &str, tr: &mut dyn Transaction) -> Option<SqlError> {
492 let mut p = Parser::new(source, self);
493 let result = std::panic::catch_unwind(panic::AssertUnwindSafe(|| {
494 p.batch(tr);
495 }));
496 if let Err(x) = result {
497 Some(if let Some(e) = x.downcast_ref::<SqlError>() {
498 SqlError {
499 msg: e.msg.clone(),
500 line: e.line,
501 column: e.column,
502 rname: e.rname.clone(),
503 }
504 } else if let Some(s) = x.downcast_ref::<&str>() {
505 p.make_error((*s).to_string())
506 } else if let Some(s) = x.downcast_ref::<String>() {
507 p.make_error(s.to_string())
508 } else {
509 p.make_error("unrecognised/unexpected error".to_string())
510 })
511 } else {
512 None
513 }
514 }
515
516 pub fn changed(self: &DB) -> bool {
518 if self.err.get() {
519 return false;
520 }
521 for bs in &self.bs {
522 if bs.changed() {
523 return true;
524 }
525 }
526 for t in self.tables.borrow().values() {
527 if t.id_gen_dirty.get() {
528 return true;
529 }
530 if t.file.changed() {
531 return true;
532 }
533 }
534 false
535 }
536
537 pub fn save(self: &DB) -> usize {
540 let op = if self.err.get() {
541 self.err.set(false);
542 SaveOp::RollBack
543 } else {
544 SaveOp::Save
545 };
546 for bs in &self.bs {
547 bs.save(self, op);
548 }
549 let tm = &*self.tables.borrow();
550 for t in tm.values() {
551 if t.id_gen_dirty.get() {
552 if op == SaveOp::Save {
553 sys::save_id_gen(self, t.id as u64, t.id_gen.get().unwrap());
554 } else {
555 t.id_gen.set(None);
556 }
557 t.id_gen_dirty.set(false);
558 }
559 }
560 for t in tm.values() {
561 t.save(self, op);
562 }
563 if self.function_reset.get() {
564 for function in self.functions.borrow().values() {
565 function.ilist.borrow_mut().clear();
566 }
567 self.functions.borrow_mut().clear();
568 self.function_reset.set(false);
569 }
570 self.apd.save(op)
571 }
572
573 #[cfg(not(feature = "table"))]
574 fn get_table(self: &DB, name: &ObjRef) -> Option<Rc<Table>> {
576 if let Some(t) = self.tables.borrow().get(name) {
577 return Some(t.clone());
578 }
579 sys::get_table(self, name)
580 }
581
582 #[cfg(feature = "table")]
583 pub fn get_table(self: &DB, name: &ObjRef) -> Option<Rc<Table>> {
585 if let Some(t) = self.tables.borrow().get(name) {
586 return Some(t.clone());
587 }
588 sys::get_table(self, name)
589 }
590
591 #[cfg(feature = "table")]
592 pub fn table(self: &DB, schema: &str, name: &str) -> Rc<Table> {
594 self.get_table(&ObjRef::new(schema, name)).unwrap()
595 }
596
597 fn get_function(self: &DB, name: &ObjRef) -> Option<Rc<Function>> {
599 if let Some(f) = self.functions.borrow().get(name) {
600 return Some(f.clone());
601 }
602 sys::get_function(self, name)
603 }
604
605 fn publish_table(&self, table: Rc<Table>) {
607 let name = table.info.name.clone();
608 self.tables.borrow_mut().insert(name, table);
609 }
610
611 fn encode(self: &DB, val: &Value, size: usize) -> Code {
613 let bytes = match val {
614 Value::RcBinary(x) => &**x,
615 Value::ArcBinary(x) => &**x,
616 Value::String(x) => x.as_bytes(),
617 _ => {
618 return Code {
619 id: u64::MAX,
620 ft: 0,
621 };
622 }
623 };
624 if bytes.len() < size {
625 return Code {
626 id: u64::MAX,
627 ft: 0,
628 };
629 }
630 let tbe = &bytes[size - 9..];
631 let ft = bytes::fragment_type(tbe.len(), &self.bpf);
632 let id = self.bs[ft].encode(self, &bytes[size - 9..]);
633 Code { id, ft }
634 }
635
636 fn decode(self: &DB, code: Code, inline: usize) -> Vec<u8> {
638 self.bs[code.ft].decode(self, code.id, inline)
639 }
640
641 fn delcode(self: &DB, code: Code) {
643 if code.id != u64::MAX {
644 self.bs[code.ft].delcode(self, code.id);
645 }
646 }
647
648 fn alloc_page(self: &DB) -> u64 {
650 self.apd.alloc_page()
651 }
652
653 fn free_page(self: &DB, lpnum: u64) {
655 self.apd.free_page(lpnum);
656 }
657
658 #[cfg(feature = "pack")]
659 fn lp_size(&self, pnum: u64) -> u64 {
661 self.apd.spd.ps.read().unwrap().size(pnum) as u64
662 }
663
664 #[cfg(feature = "pack")]
665 fn repack_file(self: &DB, k: i64, schema: &str, tname: &str) -> i64 {
667 if k >= 0 {
668 let name = ObjRef::new(schema, tname);
669 if let Some(t) = self.get_table(&name) {
670 return t.repack(self, k as usize);
671 }
672 } else {
673 let k = (-k - 1) as usize;
674 if k < 4 {
675 return self.bs[k].repack_file(self);
676 }
677 }
678 -1
679 }
680
681 #[cfg(feature = "verify")]
682 pub fn verify(self: &DB) -> String {
684 let (mut pages, total) = self.apd.spd.ps.write().unwrap().get_free();
685 let total = total as usize;
686
687 let free = pages.len();
688
689 for bs in &self.bs {
690 bs.file.get_used(self, &mut pages);
691 }
692
693 for t in self.tables.borrow().values() {
694 t.get_used(self, &mut pages);
695 }
696
697 assert_eq!(pages.len(), total);
698
699 format!(
700 "Logical page summary: free={} used={} total={}",
701 free,
702 total - free,
703 total
704 )
705 }
706
707 #[cfg(feature = "renumber")]
709 pub fn renumber(self: &DB) {
710 let target = self.apd.spd.ps.write().unwrap().load_free_pages();
711 if let Some(target) = target {
712 for bs in &self.bs {
713 bs.file.renumber(self, target);
714 }
715 for t in self.tables.borrow().values() {
716 let tf = &t.file;
717 let mut root_page = tf.root_page.get();
718 if root_page >= target {
719 root_page = tf.ren(root_page, self);
720 tf.root_page.set(root_page);
721 sys::set_root(self, t.id, root_page);
722 }
723 tf.renumber(self, target);
724 for ix in &mut *t.ixlist.borrow_mut() {
725 let mut root_page = ix.file.root_page.get();
726 if root_page >= target {
727 root_page = ix.file.ren(root_page, self);
728 ix.file.root_page.set(root_page);
729 sys::set_ix_root(self, ix.id, root_page);
730 }
731 ix.file.renumber(self, target);
732 }
733 }
734 self.apd.spd.ps.write().unwrap().set_alloc_pn(target);
735 }
736 }
737} impl Drop for Database {
740 fn drop(&mut self) {
742 for function in self.functions.borrow().values() {
743 function.ilist.borrow_mut().clear();
744 }
745 }
746}
747
748struct TableBuilder {
750 alloc: usize,
751 list: Vec<Rc<Table>>,
752}
753impl TableBuilder {
754 fn new() -> Self {
755 Self {
756 alloc: bytes::NFT,
757 list: Vec::new(),
758 }
759 }
760
761 fn nt(&mut self, name: &str, ct: &[(&str, DataType)]) -> Rc<Table> {
762 let root = self.rt();
763 let id = 1 + (root - bytes::NFT as u64);
764 let name = ObjRef::new("sys", name);
765 let info = ColInfo::new(name, ct);
766 let table = Table::new(id as i64, root, 1, Rc::new(info));
767 self.list.push(table.clone());
768 table
769 }
770
771 fn rt(&mut self) -> u64 {
772 let result = self.alloc;
773 self.alloc += 1;
774 result as u64
775 }
776}
777
778pub trait Transaction: Any {
780 fn status_code(&mut self, _code: i64) {}
782
783 fn header(&mut self, _name: &str, _value: &str) {}
785
786 fn selected(&mut self, values: &[Value]);
788
789 fn global(&self, _kind: i64) -> i64 {
791 0
792 }
793
794 fn arg(&mut self, _kind: i64, _name: &str) -> Rc<String> {
796 Rc::new(String::new())
797 }
798
799 fn file_attr(&mut self, _fnum: i64, _atx: i64) -> Rc<String> {
801 Rc::new(String::new())
802 }
803
804 fn file_content(&mut self, _fnum: i64) -> Arc<Vec<u8>> {
806 nd()
807 }
808
809 fn set_error(&mut self, err: String);
811
812 fn get_error(&mut self) -> String {
814 String::new()
815 }
816
817 fn set_extension(&mut self, _ext: Box<dyn Any + Send + Sync>) {}
819
820 fn get_extension(&mut self) -> Box<dyn Any + Send + Sync> {
822 Box::new(())
823 }
824}
825
826struct DummyTransaction {}
828impl Transaction for DummyTransaction {
829 fn selected(&mut self, _values: &[Value]) {}
830 fn set_error(&mut self, err: String) {
832 println!("Error: {}", err);
833 }
834}
835
836#[non_exhaustive]
838pub struct Limits {
839 pub af_lim: atom_file::Limits,
841 pub blk_cap: u64,
843 pub page_sizes: usize,
845 pub max_div: usize,
847}
848
849impl Default for Limits {
850 fn default() -> Self {
851 Self {
852 af_lim: atom_file::Limits::default(),
853 blk_cap: 27720,
854 page_sizes: 7,
855 max_div: 12,
856 }
857 }
858}