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