├── README.md ├── build ├── dbcreate.d ├── dbdestroy.d ├── ix_error.d ├── ix_indexhandle.d ├── ix_indexscan.d ├── ix_manager.d ├── ix_test.d ├── ix_test_simple.d ├── ix_tester.d ├── ix_testjl.d ├── ix_testkpg_2.d ├── ix_testpark.d ├── parser_test.d ├── pf_buffermgr.d ├── pf_buffermgr.o ├── pf_error.d ├── pf_error.o ├── pf_filehandle.d ├── pf_filehandle.o ├── pf_hashtable.d ├── pf_hashtable.o ├── pf_manager.d ├── pf_manager.o ├── pf_pagehandle.d ├── pf_pagehandle.o ├── pf_statistics.d ├── pf_statistics.o ├── pf_test1.d ├── pf_test1.o ├── pf_test2.d ├── pf_test2.o ├── pf_test3.d ├── pf_test3.o ├── printer.d ├── ql_error.d ├── ql_manager.d ├── ql_node.d ├── ql_nodejoin.d ├── ql_nodeproj.d ├── ql_noderel.d ├── ql_nodesel.d ├── qo_manager.d ├── redbase.d ├── rm_error.d ├── rm_filehandle.d ├── rm_filescan.d ├── rm_manager.d ├── rm_manager.d.16355 ├── rm_record.d ├── rm_record.d.1603 ├── rm_record.d.1607 ├── rm_record.d.1638 ├── rm_record.d.1643 ├── rm_record.d.1680 ├── rm_record.d.1747 ├── rm_rid.d ├── rm_test.d ├── rm_test.d.11801 ├── rm_test.d.11806 ├── rm_test.d.11811 ├── rm_test.d.11817 ├── rm_test.d.11923 ├── rm_testgmf.d ├── rm_testkpg.d ├── rm_testrecsizes.d ├── rm_testshnFIXED.d ├── rm_testyh_random.d ├── sm_attriterator.d ├── sm_error.d ├── sm_manager.d ├── statistics.d └── statistics.o ├── doc ├── ix_DOC ├── ql_DOC ├── query_optimizer_DOC.pdf ├── rm_DOC └── sm_DOC ├── lib ├── libix.a ├── libparser.a ├── libpf.a ├── libql.a ├── librm.a └── libsm.a ├── setup └── src ├── Makefile ├── Parser.HowTo ├── comparators.h ├── data.txt ├── dbcreate.cc ├── dbdestroy ├── dbdestroy.cc ├── interp.c ├── ix.h ├── ix_error.cc ├── ix_indexhandle.cc ├── ix_indexscan.cc ├── ix_internal.h ├── ix_manager.cc ├── linkedlist.h ├── node.cc ├── node_comps.h ├── node_proj.cc ├── node_rel.cc ├── node_sel.cc ├── nodes.c ├── parse.c ├── parse.y ├── parser.h ├── parser_internal.h ├── parser_test.cc ├── pf.h ├── pf_buffermgr.cc ├── pf_buffermgr.h ├── pf_error.cc ├── pf_filehandle.cc ├── pf_hashtable.cc ├── pf_hashtable.h ├── pf_internal.h ├── pf_manager.cc ├── pf_pagehandle.cc ├── pf_statistics.cc ├── printer.cc ├── printer.h ├── ql.h ├── ql_error.cc ├── ql_manager.cc ├── ql_manager_stub.cc ├── ql_node.cc ├── ql_node.h ├── ql_nodejoin.cc ├── ql_nodeproj.cc ├── ql_noderel.cc ├── ql_nodesel.cc ├── ql_test.tester ├── qo.h ├── qo_manager.cc ├── redbase.cc ├── redbase.h ├── rm.h ├── rm_error.cc ├── rm_filehandle.cc ├── rm_filescan.cc ├── rm_internal.h ├── rm_manager.cc ├── rm_record.cc ├── rm_rid.cc ├── rm_rid.h ├── scan.c ├── scan.l ├── scanhelp.c ├── sm.h ├── sm_attriterator.cc ├── sm_error.cc ├── sm_manager.cc ├── sm_stub.cc ├── statistics.cc ├── statistics.h ├── submit ├── submit.ix ├── submit.ql ├── submit.rm ├── submit.sm └── y.tab.h /README.md: -------------------------------------------------------------------------------- 1 | redbase 2 | ======= 3 | 4 | A mini relational databased for the CS346 Stanford class. See the website for more details: http://web.stanford.edu/class/cs346/project.html 5 | 6 | To compile, type "make". 7 | 8 | To create a database: 9 | ./dbcreate "dbname" 10 | 11 | To use the database created: 12 | ./redbase "dbname" 13 | 14 | To destroy the database: 15 | ./dbdestroy "dbname" 16 | 17 | My implementation documentation for each layer can be found in the "doc" folder. 18 | 19 | Here is a VERY high level overview for the "parts" of the system: 20 | RM - Record Manager 21 | The Record manager organizes pages into databases. It keeps a header page with 22 | informaiton about the record sizes, the number of pages in the table, etc. Each 23 | page mantains information about how the records are stored on the page. There 24 | is also an iterator for scanning through the records of the table 25 | 26 | IX - Index Layer 27 | This layer holds the index layer. It manages a set of pages that store the nodes 28 | of the B+ tree, and implements the logic of insertion, deletion, and search. There 29 | is also an iterator for retrieving indices, with or without conditions. 30 | 31 | SM - System Management 32 | Files involved with this have to do with creating, destroying and manipulating the 33 | database. When the appropriate instructions are given by the user to redbase, 34 | SM will organize the files for keeping track of databases, tables, indices. It 35 | also deals with loading data into databases. 36 | 37 | QL - Query Layer 38 | This is the most interesting part of the system. It takes the output of the parser 39 | (that was given to us) and implements the appropraite SQL query. Details of what 40 | is implemented is in http://web.stanford.edu/class/cs346/ql.html. 41 | The QL layer constructs the query tree plan, and executes them with iterators. It 42 | constructs the tree with objects that I've called "nodes" in the files, and 43 | keeps a pointer to the root. Then, when a record is requested from the root, it 44 | recursively calls for the next record from the leaves. 45 | 46 | The additional component I implemented was a dynamic programming query optimizer. 47 | The documentation is in the pdf labeled query_optimizer_DOC. 48 | 49 | It is a simplified version of the Selinger Query Optimizer that uses only 50 | dynamic programming. It keeps an estimate of the number of records and unique 51 | values of each attribute for each table, and uses estimates to determine 52 | the order of the join. See query_optimizer_DOC for more details! :) 53 | -------------------------------------------------------------------------------- /build/dbcreate.d: -------------------------------------------------------------------------------- 1 | ../build/dbcreate.o ../build/dbcreate.d: dbcreate.cc rm.h redbase.h rm_rid.h pf.h sm.h \ 2 | parser.h ix.h printer.h 3 | -------------------------------------------------------------------------------- /build/dbdestroy.d: -------------------------------------------------------------------------------- 1 | ../build/dbdestroy.o ../build/dbdestroy.d: dbdestroy.cc rm.h redbase.h rm_rid.h pf.h sm.h \ 2 | parser.h ix.h printer.h 3 | -------------------------------------------------------------------------------- /build/ix_error.d: -------------------------------------------------------------------------------- 1 | ../build/ix_error.o ../build/ix_error.d: ix_error.cc ix_internal.h ix.h redbase.h rm_rid.h \ 2 | pf.h 3 | -------------------------------------------------------------------------------- /build/ix_indexhandle.d: -------------------------------------------------------------------------------- 1 | ../build/ix_indexhandle.o ../build/ix_indexhandle.d: ix_indexhandle.cc pf.h redbase.h ix_internal.h \ 2 | ix.h rm_rid.h comparators.h 3 | -------------------------------------------------------------------------------- /build/ix_indexscan.d: -------------------------------------------------------------------------------- 1 | ../build/ix_indexscan.o ../build/ix_indexscan.d: ix_indexscan.cc pf.h redbase.h ix_internal.h \ 2 | ix.h rm_rid.h 3 | -------------------------------------------------------------------------------- /build/ix_manager.d: -------------------------------------------------------------------------------- 1 | ../build/ix_manager.o ../build/ix_manager.d: ix_manager.cc pf.h redbase.h ix_internal.h ix.h \ 2 | rm_rid.h comparators.h 3 | -------------------------------------------------------------------------------- /build/ix_test.d: -------------------------------------------------------------------------------- 1 | ../build/ix_test.o ../build/ix_test.d: ix_test.cc redbase.h pf.h rm.h rm_rid.h ix.h 2 | -------------------------------------------------------------------------------- /build/ix_test_simple.d: -------------------------------------------------------------------------------- 1 | ../build/ix_test_simple.o ../build/ix_test_simple.d: ix_test_simple.cc redbase.h pf.h rm.h rm_rid.h \ 2 | ix.h 3 | -------------------------------------------------------------------------------- /build/ix_tester.d: -------------------------------------------------------------------------------- 1 | ../build/ix_tester.o ../build/ix_tester.d: ix_tester.cc redbase.h ix.h rm_rid.h pf.h 2 | -------------------------------------------------------------------------------- /build/ix_testjl.d: -------------------------------------------------------------------------------- 1 | ../build/ix_testjl.o ../build/ix_testjl.d: ix_testjl.cc redbase.h pf.h rm.h rm_rid.h ix.h 2 | -------------------------------------------------------------------------------- /build/ix_testkpg_2.d: -------------------------------------------------------------------------------- 1 | ../build/ix_testkpg_2.o ../build/ix_testkpg_2.d: ix_testkpg_2.cc redbase.h pf.h rm.h rm_rid.h \ 2 | ix.h 3 | -------------------------------------------------------------------------------- /build/ix_testpark.d: -------------------------------------------------------------------------------- 1 | ../build/ix_testpark.o ../build/ix_testpark.d: ix_testpark.cc redbase.h pf.h rm.h rm_rid.h ix.h 2 | -------------------------------------------------------------------------------- /build/parser_test.d: -------------------------------------------------------------------------------- 1 | ../build/parser_test.o ../build/parser_test.d: parser_test.cc redbase.h parser.h pf.h sm.h rm.h \ 2 | rm_rid.h ix.h printer.h ql.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/pf_buffermgr.d: -------------------------------------------------------------------------------- 1 | ../build/pf_buffermgr.o ../build/pf_buffermgr.d: pf_buffermgr.cc pf_buffermgr.h pf_internal.h \ 2 | pf.h redbase.h pf_hashtable.h statistics.h linkedlist.h 3 | -------------------------------------------------------------------------------- /build/pf_buffermgr.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_buffermgr.o -------------------------------------------------------------------------------- /build/pf_error.d: -------------------------------------------------------------------------------- 1 | ../build/pf_error.o ../build/pf_error.d: pf_error.cc pf_internal.h pf.h redbase.h 2 | -------------------------------------------------------------------------------- /build/pf_error.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_error.o -------------------------------------------------------------------------------- /build/pf_filehandle.d: -------------------------------------------------------------------------------- 1 | ../build/pf_filehandle.o ../build/pf_filehandle.d: pf_filehandle.cc pf_internal.h pf.h redbase.h \ 2 | pf_buffermgr.h pf_hashtable.h 3 | -------------------------------------------------------------------------------- /build/pf_filehandle.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_filehandle.o -------------------------------------------------------------------------------- /build/pf_hashtable.d: -------------------------------------------------------------------------------- 1 | ../build/pf_hashtable.o ../build/pf_hashtable.d: pf_hashtable.cc pf_internal.h pf.h redbase.h \ 2 | pf_hashtable.h 3 | -------------------------------------------------------------------------------- /build/pf_hashtable.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_hashtable.o -------------------------------------------------------------------------------- /build/pf_manager.d: -------------------------------------------------------------------------------- 1 | ../build/pf_manager.o ../build/pf_manager.d: pf_manager.cc pf_internal.h pf.h redbase.h \ 2 | pf_buffermgr.h pf_hashtable.h 3 | -------------------------------------------------------------------------------- /build/pf_manager.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_manager.o -------------------------------------------------------------------------------- /build/pf_pagehandle.d: -------------------------------------------------------------------------------- 1 | ../build/pf_pagehandle.o ../build/pf_pagehandle.d: pf_pagehandle.cc pf_internal.h pf.h redbase.h 2 | -------------------------------------------------------------------------------- /build/pf_pagehandle.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_pagehandle.o -------------------------------------------------------------------------------- /build/pf_statistics.d: -------------------------------------------------------------------------------- 1 | ../build/pf_statistics.o ../build/pf_statistics.d: pf_statistics.cc pf.h redbase.h statistics.h \ 2 | linkedlist.h 3 | -------------------------------------------------------------------------------- /build/pf_statistics.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_statistics.o -------------------------------------------------------------------------------- /build/pf_test1.d: -------------------------------------------------------------------------------- 1 | ../build/pf_test1.o ../build/pf_test1.d: pf_test1.cc pf.h redbase.h pf_internal.h \ 2 | pf_hashtable.h statistics.h linkedlist.h 3 | -------------------------------------------------------------------------------- /build/pf_test1.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_test1.o -------------------------------------------------------------------------------- /build/pf_test2.d: -------------------------------------------------------------------------------- 1 | ../build/pf_test2.o ../build/pf_test2.d: pf_test2.cc pf.h redbase.h pf_internal.h \ 2 | pf_hashtable.h statistics.h linkedlist.h 3 | -------------------------------------------------------------------------------- /build/pf_test2.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_test2.o -------------------------------------------------------------------------------- /build/pf_test3.d: -------------------------------------------------------------------------------- 1 | ../build/pf_test3.o ../build/pf_test3.d: pf_test3.cc pf.h redbase.h pf_internal.h \ 2 | pf_hashtable.h 3 | -------------------------------------------------------------------------------- /build/pf_test3.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/pf_test3.o -------------------------------------------------------------------------------- /build/printer.d: -------------------------------------------------------------------------------- 1 | ../build/printer.o ../build/printer.d: printer.cc printer.h redbase.h 2 | -------------------------------------------------------------------------------- /build/ql_error.d: -------------------------------------------------------------------------------- 1 | ../build/ql_error.o ../build/ql_error.d: ql_error.cc ql.h redbase.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h sm.h printer.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/ql_manager.d: -------------------------------------------------------------------------------- 1 | ../build/ql_manager.o ../build/ql_manager.d: ql_manager.cc redbase.h ql.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h sm.h printer.h ql_node.h qo.h 3 | -------------------------------------------------------------------------------- /build/ql_node.d: -------------------------------------------------------------------------------- 1 | ../build/ql_node.o ../build/ql_node.d: ql_node.cc redbase.h sm.h parser.h pf.h rm.h rm_rid.h \ 2 | ix.h printer.h ql.h ql_node.h node_comps.h comparators.h 3 | -------------------------------------------------------------------------------- /build/ql_nodejoin.d: -------------------------------------------------------------------------------- 1 | ../build/ql_nodejoin.o ../build/ql_nodejoin.d: ql_nodejoin.cc redbase.h sm.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h ql.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/ql_nodeproj.d: -------------------------------------------------------------------------------- 1 | ../build/ql_nodeproj.o ../build/ql_nodeproj.d: ql_nodeproj.cc redbase.h sm.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h ql.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/ql_noderel.d: -------------------------------------------------------------------------------- 1 | ../build/ql_noderel.o ../build/ql_noderel.d: ql_noderel.cc redbase.h sm.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h ql.h ql_node.h comparators.h 3 | -------------------------------------------------------------------------------- /build/ql_nodesel.d: -------------------------------------------------------------------------------- 1 | ../build/ql_nodesel.o ../build/ql_nodesel.d: ql_nodesel.cc redbase.h sm.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h ql.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/qo_manager.d: -------------------------------------------------------------------------------- 1 | ../build/qo_manager.o ../build/qo_manager.d: qo_manager.cc redbase.h ql.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h sm.h printer.h ql_node.h qo.h 3 | -------------------------------------------------------------------------------- /build/redbase.d: -------------------------------------------------------------------------------- 1 | ../build/redbase.o ../build/redbase.d: redbase.cc redbase.h rm.h rm_rid.h pf.h sm.h parser.h \ 2 | ix.h printer.h ql.h ql_node.h 3 | -------------------------------------------------------------------------------- /build/rm_error.d: -------------------------------------------------------------------------------- 1 | ../build/rm_error.o ../build/rm_error.d: rm_error.cc rm_internal.h pf.h redbase.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_filehandle.d: -------------------------------------------------------------------------------- 1 | ../build/rm_filehandle.o ../build/rm_filehandle.d: rm_filehandle.cc pf.h redbase.h rm_internal.h \ 2 | rm.h rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_filescan.d: -------------------------------------------------------------------------------- 1 | ../build/rm_filescan.o ../build/rm_filescan.d: rm_filescan.cc pf.h redbase.h rm_internal.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_manager.d: -------------------------------------------------------------------------------- 1 | ../build/rm_manager.o ../build/rm_manager.d: rm_manager.cc pf.h redbase.h rm_internal.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_manager.d.16355: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_manager.d.16355 -------------------------------------------------------------------------------- /build/rm_record.d: -------------------------------------------------------------------------------- 1 | ../build/rm_record.o ../build/rm_record.d: rm_record.cc pf.h redbase.h rm_internal.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_record.d.1603: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1603 -------------------------------------------------------------------------------- /build/rm_record.d.1607: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1607 -------------------------------------------------------------------------------- /build/rm_record.d.1638: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1638 -------------------------------------------------------------------------------- /build/rm_record.d.1643: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1643 -------------------------------------------------------------------------------- /build/rm_record.d.1680: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1680 -------------------------------------------------------------------------------- /build/rm_record.d.1747: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_record.d.1747 -------------------------------------------------------------------------------- /build/rm_rid.d: -------------------------------------------------------------------------------- 1 | ../build/rm_rid.o ../build/rm_rid.d: rm_rid.cc rm_rid.h redbase.h rm_internal.h pf.h rm.h 2 | -------------------------------------------------------------------------------- /build/rm_test.d: -------------------------------------------------------------------------------- 1 | ../build/rm_test.o ../build/rm_test.d: rm_test.cc redbase.h pf.h rm_internal.h rm.h rm_rid.h 2 | -------------------------------------------------------------------------------- /build/rm_test.d.11801: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_test.d.11801 -------------------------------------------------------------------------------- /build/rm_test.d.11806: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_test.d.11806 -------------------------------------------------------------------------------- /build/rm_test.d.11811: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_test.d.11811 -------------------------------------------------------------------------------- /build/rm_test.d.11817: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_test.d.11817 -------------------------------------------------------------------------------- /build/rm_test.d.11923: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/rm_test.d.11923 -------------------------------------------------------------------------------- /build/rm_testgmf.d: -------------------------------------------------------------------------------- 1 | ../build/rm_testgmf.o ../build/rm_testgmf.d: rm_testgmf.cc redbase.h pf.h rm_internal.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_testkpg.d: -------------------------------------------------------------------------------- 1 | ../build/rm_testkpg.o ../build/rm_testkpg.d: rm_testkpg.cc redbase.h pf.h rm.h rm_rid.h 2 | -------------------------------------------------------------------------------- /build/rm_testrecsizes.d: -------------------------------------------------------------------------------- 1 | ../build/rm_testrecsizes.o ../build/rm_testrecsizes.d: rm_testrecsizes.cc redbase.h pf.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_testshnFIXED.d: -------------------------------------------------------------------------------- 1 | ../build/rm_testshnFIXED.o ../build/rm_testshnFIXED.d: rm_testshnFIXED.cc redbase.h pf.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/rm_testyh_random.d: -------------------------------------------------------------------------------- 1 | ../build/rm_testyh_random.o ../build/rm_testyh_random.d: rm_testyh_random.cc redbase.h pf.h rm.h \ 2 | rm_rid.h 3 | -------------------------------------------------------------------------------- /build/sm_attriterator.d: -------------------------------------------------------------------------------- 1 | ../build/sm_attriterator.o ../build/sm_attriterator.d: sm_attriterator.cc rm.h redbase.h rm_rid.h \ 2 | pf.h sm.h parser.h ix.h printer.h 3 | -------------------------------------------------------------------------------- /build/sm_error.d: -------------------------------------------------------------------------------- 1 | ../build/sm_error.o ../build/sm_error.d: sm_error.cc sm.h redbase.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h 3 | -------------------------------------------------------------------------------- /build/sm_manager.d: -------------------------------------------------------------------------------- 1 | ../build/sm_manager.o ../build/sm_manager.d: sm_manager.cc redbase.h sm.h parser.h pf.h rm.h \ 2 | rm_rid.h ix.h printer.h statistics.h linkedlist.h 3 | -------------------------------------------------------------------------------- /build/statistics.d: -------------------------------------------------------------------------------- 1 | ../build/statistics.o ../build/statistics.d: statistics.cc statistics.h linkedlist.h 2 | -------------------------------------------------------------------------------- /build/statistics.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/build/statistics.o -------------------------------------------------------------------------------- /doc/ix_DOC: -------------------------------------------------------------------------------- 1 | Overall Design: 2 | On the Index File level: 3 | Each index file has a header page that contains the basic information about the 4 | index: the attribute type, the attribute length, the root page number, as well 5 | as information about the offsets of the entries in tree/bucket pages (explained 6 | more later). When a file is open, these header contents on the first page are 7 | copied into the indexHandle header object for easy reference. The first page is 8 | unpinned to leave more room in the buffer. When the index is closed, the 9 | contents of the header page are updated if they have been modified. 10 | 11 | Furthermore, each file has a root page that is always pinned while the index 12 | is open. This is because it is accessed a lot, so it makes sense to keep it 13 | pinned in buffer. 14 | 15 | The tree: 16 | For the most part, this tree is structured like a normal B+ tree. Each node 17 | contains a header (indicating whether it's a leaf node, if it's empty, and 18 | number of keys that it contains), a list of entries (which contain a flag for 19 | whether the entry exists, is a duplicate, or a singleton, the index location of 20 | the next entry, and the page/slot number), and a list of keys. To make things 21 | easier to implement, the leaf nodes look exactly like the internal nodes 22 | (except the internal nodes do not use the "slot" field for each entry, just the 23 | "page" field that points to the page numbers of its child nodes). In addition 24 | to the general header, each internal node contains a PageNum of the first page 25 | that it points to, and each leaf node contains pointers to the next and 26 | previous leaf nodes in the tree. 27 | 28 | To keep the order of the entries/keys, I keep a singly-linked list of free 29 | slots and used slots. When a node is initialized, the free list is set up. When 30 | a value needs to be insert into a location in the list, I retrieve the index 31 | preceding the location that I want to insert it in, and update that index's 32 | "nextSlot" pointer to the next free location, and insert my new value there. 33 | When an entry is deleted, it is added to the beginning of the free list. 34 | 35 | As long as duplicate values are not inserted, the RIDs are kept at the leaf 36 | nodes (at the variables "page" and "slot" in Node_Entry in the leaf nodes). 37 | However, when a duplicate is inserted, then a bucket page is created for all 38 | those duplicates. The indicator "isValid" is updated to OCCUPIED_DUP (from 39 | OCCUPIED_NEW), and the "page" field is set to the PageNum of the new bucket. 40 | When enough duplicates that are inserted overfills this bucket, then a new 41 | bucket is added, and the previous bucket header's "nextBucket" field is set to 42 | this new bucket. 43 | 44 | Insertion: 45 | I basically took the insertion algorithm from this page: 46 | http://www.di.ufpb.br/lucidio/Btrees.pdf. 47 | However, I had to modify it a bit because of the bucketing that I do. 48 | Basically, the algorithm takes advantage of the fact that nodes are split at the 49 | root. Whenever we want to insert into a full node, we split it first, and then 50 | insert into that node. 51 | 52 | Deletion: 53 | I decided to do lazy deletion. Whenever an entry is deleted, I will mark it as 54 | deleted, but the space occupied by that entry can then be reused. When a 55 | bucket, a leaf, or an internal node is empty, I will delete it from the tree. 56 | When all contents of the tree are deleted (and the we are asked to delete the 57 | root page), we will set the root page to be a leaf node. 58 | 59 | To make deletion consistent with insertion, I need to make sure that when an 60 | value goes from OCCUPIED_DUP to OCCUPIED_NEW, I move the entry into the leaf 61 | node and delete the bucket. This is done by marking a bucket as "to-be-deleted" 62 | if there is only one entry inside of it, and passing that entry from the last 63 | bucket to the previous bucket, or the leaf associated with that bucket. If the 64 | previous bucket has room, it will move this last entry into itself. If it 65 | doesn't, it will do so next time something is deleted from it because of the 66 | recursive nature of the algorithm. This ensures that if there is only one 67 | value of a key, it will always be found in the leaf. 68 | 69 | Search: 70 | Because of the way I do bucketing and deletion, I had to be more clever with my 71 | search in terms to be able to delete while searching. Basically, as I delete, 72 | I know that the following record might change places (move from one bucket to 73 | the previous bucket) in the middle of the search. Therefore, the state of the 74 | search will always be two entries ahead of the current RID that it returns. 75 | This also ensures that the can does not keep a bucket or leaf pinned if the 76 | delete algorithm wants to delete that bucket or leaf. Scan will keep two RIDs 77 | in its private variables: the current RID to return, and the RID of the next 78 | element to return. If the scan state has reached the end of the file, it sets 79 | the next RID to an invalid value. Before returning the current RID, scan checks 80 | whether it's a valid RID. If not, it knows that there are no more values, so it 81 | returns IX_EOF. 82 | 83 | Testing Process: 84 | I tested by running all the tests in the class test folder. This includes 85 | ix_testkpg2, ix_tester, ix_testpark, and ix_testjl. I didn't really have time 86 | to create my own tests, but I did tweak some of ix_testkpg2's tests to 87 | incorporate more entries (to expand my buckets, or leaves). I also write a 88 | test that inserts a given number of random values, all a given number of times. 89 | Then, it deletes a random number of each, and checks that the count of the 90 | remaining keys that exists are the appropriate numbers. 91 | 92 | Known Bugs: 93 | Not yet? 94 | 95 | Additional Help: 96 | I talked a lot with Jaeho about the best way to implement a B+ tree to take 97 | into account infinite duplicates. I talked briefly with Sophia Nguyen about 98 | basic design at the very beginning of the assignment, but I did not discuss 99 | with anybody while doing the actual implementation. I also consulted this 100 | website: http://www.di.ufpb.br/lucidio/Btrees.pdf for the insertion algorithm. 101 | -------------------------------------------------------------------------------- /doc/ql_DOC: -------------------------------------------------------------------------------- 1 | The QL component is divided into 3 components: 2 | 1. Parsing 3 | 2. Node generation 4 | 3. Running 5 | 6 | In the parsing stage, we make sure that the query entered is a valid query. 7 | During this stage, it creates a list of relation entries and a list of attribute 8 | entries. The relation entries are put in an array in the order that they are 9 | entered. The attribute entries are also in the order that they appear in the 10 | relation, and if i 2 | -------------------------------------------------------------------------------- /lib/libparser.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /lib/libpf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/lib/libpf.a -------------------------------------------------------------------------------- /lib/libql.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /lib/librm.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /lib/libsm.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /setup: -------------------------------------------------------------------------------- 1 | /usr/class/cs346/redbase/scripts/setup -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the RedBase project. 3 | # 4 | # Author: Hyunjung Park (hyunjung@cs.stanford.edu) 5 | # 6 | 7 | 8 | # 9 | # Global variables 10 | # 11 | CC = g++ 12 | BUILD_DIR = ../build/ 13 | LIB_DIR = ../lib/ 14 | INC_DIRS = -I. 15 | AR = ar -rc 16 | RANLIB = ranlib 17 | YACC = bison -dy 18 | LEX = flex 19 | 20 | # -m32 - Generates code that runs on any i386 system 21 | # sizeof(int) = sizeof(long) = sizeof(void *) = 4 22 | # -g - Debugging information 23 | # -O1 - Basic optimization 24 | # -Wall - All warnings 25 | # -DDEBUG_PF - This turns on the LOG file for lots of BufferMgr info 26 | CFLAGS = -m32 -g -O1 -Wall $(STATS_OPTION) $(INC_DIRS) 27 | 28 | # The STATS_OPTION can be set to -DPF_STATS or to nothing to turn on and 29 | # off buffer manager statistics. The student should not modify this 30 | # flag at all! 31 | STATS_OPTION = -DPF_STATS 32 | 33 | # 34 | # Students: Please modify SOURCES variables as needed. 35 | # 36 | PF_SOURCES = pf_buffermgr.cc pf_error.cc pf_filehandle.cc \ 37 | pf_pagehandle.cc pf_hashtable.cc pf_manager.cc \ 38 | pf_statistics.cc statistics.cc 39 | RM_SOURCES = rm_manager.cc rm_filehandle.cc rm_record.cc \ 40 | rm_filescan.cc rm_error.cc rm_rid.cc 41 | IX_SOURCES = ix_manager.cc ix_indexhandle.cc ix_indexscan.cc ix_error.cc 42 | SM_SOURCES = sm_manager.cc printer.cc sm_error.cc sm_attriterator.cc 43 | QL_SOURCES = ql_error.cc ql_manager.cc ql_node.cc ql_nodeproj.cc ql_noderel.cc ql_nodejoin.cc ql_nodesel.cc qo_manager.cc 44 | UTILS_SOURCES = dbcreate.cc dbdestroy.cc redbase.cc 45 | PARSER_SOURCES = scan.c parse.c nodes.c interp.c 46 | TESTER_SOURCES = rm_testkpg.cc parser_test.cc ix_testkpg_2.cc ix_testpark.cc ix_testjl.cc ix_tester.cc ix_test_simple.cc ix_test.cc rm_testrecsizes.cc rm_testshnFIXED.cc rm_testyh_random.cc rm_test.cc rm_testgmf.cc rm_testkpg.cc #rm_testjl.cc #rm_test.cc #ix_test.cc parser_test.cc 47 | 48 | PF_OBJECTS = $(addprefix $(BUILD_DIR), $(PF_SOURCES:.cc=.o)) 49 | RM_OBJECTS = $(addprefix $(BUILD_DIR), $(RM_SOURCES:.cc=.o)) 50 | IX_OBJECTS = $(addprefix $(BUILD_DIR), $(IX_SOURCES:.cc=.o)) 51 | SM_OBJECTS = $(addprefix $(BUILD_DIR), $(SM_SOURCES:.cc=.o)) 52 | QL_OBJECTS = $(addprefix $(BUILD_DIR), $(QL_SOURCES:.cc=.o)) 53 | UTILS_OBJECTS = $(addprefix $(BUILD_DIR), $(UTILS_SOURCES:.cc=.o)) 54 | PARSER_OBJECTS = $(addprefix $(BUILD_DIR), $(PARSER_SOURCES:.c=.o)) 55 | TESTER_OBJECTS = $(addprefix $(BUILD_DIR), $(TESTER_SOURCES:.cc=.o)) 56 | OBJECTS = $(PF_OBJECTS) $(RM_OBJECTS) $(IX_OBJECTS) \ 57 | $(SM_OBJECTS) $(QL_OBJECTS) $(PARSER_OBJECTS) \ 58 | $(TESTER_OBJECTS) $(UTILS_OBJECTS) 59 | 60 | LIBRARY_PF = $(LIB_DIR)libpf.a 61 | LIBRARY_RM = $(LIB_DIR)librm.a 62 | LIBRARY_IX = $(LIB_DIR)libix.a 63 | LIBRARY_SM = $(LIB_DIR)libsm.a 64 | LIBRARY_QL = $(LIB_DIR)libql.a 65 | LIBRARY_PARSER = $(LIB_DIR)libparser.a 66 | LIBRARIES = $(LIBRARY_PF) $(LIBRARY_RM) $(LIBRARY_IX) \ 67 | $(LIBRARY_SM) $(LIBRARY_QL) $(LIBRARY_PARSER) 68 | 69 | UTILS = $(UTILS_SOURCES:.cc=) 70 | TESTS = $(TESTER_SOURCES:.cc=) 71 | EXECUTABLES = $(UTILS) $(TESTS) 72 | 73 | LIBS = -lparser -lql -lsm -lix -lrm -lpf 74 | 75 | # 76 | # Build targets 77 | # 78 | all: $(LIBRARIES) $(UTILS) 79 | 80 | clean: 81 | rm -f $(BUILD_DIR)*.o $(BUILD_DIR)*.d y.output y.tab.h parse.c $(LIBRARIES) $(EXECUTABLES) 82 | 83 | testers: all $(TESTS) 84 | 85 | # 86 | # Libraries 87 | # 88 | $(LIBRARY_PF): $(PF_OBJECTS) 89 | $(AR) $(LIBRARY_PF) $(PF_OBJECTS) 90 | $(RANLIB) $(LIBRARY_PF) 91 | 92 | $(LIBRARY_RM): $(RM_OBJECTS) 93 | $(AR) $(LIBRARY_RM) $(RM_OBJECTS) 94 | $(RANLIB) $(LIBRARY_RM) 95 | 96 | $(LIBRARY_IX): $(IX_OBJECTS) 97 | $(AR) $(LIBRARY_IX) $(IX_OBJECTS) 98 | $(RANLIB) $(LIBRARY_IX) 99 | 100 | $(LIBRARY_SM): $(SM_OBJECTS) 101 | $(AR) $(LIBRARY_SM) $(SM_OBJECTS) 102 | $(RANLIB) $(LIBRARY_SM) 103 | 104 | $(LIBRARY_QL): $(QL_OBJECTS) 105 | $(AR) $(LIBRARY_QL) $(QL_OBJECTS) 106 | $(RANLIB) $(LIBRARY_QL) 107 | 108 | $(LIBRARY_PARSER): $(PARSER_OBJECTS) 109 | $(AR) $(LIBRARY_PARSER) $(PARSER_OBJECTS) 110 | $(RANLIB) $(LIBRARY_PARSER) 111 | 112 | # 113 | # Parser 114 | # 115 | y.tab.h: parse.c 116 | 117 | parse.c: parse.y 118 | $(YACC) parse.y; mv y.tab.c parse.c 119 | 120 | scan.c: scan.l scanhelp.c y.tab.h 121 | $(LEX) scan.l; mv lex.yy.c scan.c 122 | 123 | $(BUILD_DIR)parse.o: parse.c 124 | 125 | $(BUILD_DIR)scan.o: scan.c y.tab.h 126 | 127 | $(BUILD_DIR)nodes.o: nodes.c 128 | 129 | $(BUILD_DIR)interp.o: interp.c 130 | 131 | # 132 | # Rules 133 | # 134 | -include $(OBJECTS:.o=.d) 135 | 136 | $(BUILD_DIR)%.d: %.cc 137 | @set -e; \ 138 | rm -f $@; \ 139 | $(CC) $(CFLAGS) -MM -MT $(@:.d=.o) $< > $@.$$$$; \ 140 | sed 's,\($*\)\.o[ :]*,\1.o $@: ,g' $@.$$$$ > $@; \ 141 | rm -f $@.$$$$ 142 | 143 | $(OBJECTS): %.o: 144 | $(CC) $(CFLAGS) -c $< -o $@ 145 | 146 | $(EXECUTABLES): %: $(BUILD_DIR)%.o $(LIBRARIES) 147 | $(CC) $(CFLAGS) $< -o $@ -L$(LIB_DIR) $(LIBS) 148 | 149 | -------------------------------------------------------------------------------- /src/comparators.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "pf.h" 4 | #include 5 | #include 6 | 7 | static int compare_string(void *value1, void* value2, int attrLength){ 8 | return strncmp((char *) value1, (char *) value2, attrLength); 9 | } 10 | 11 | static int compare_int(void *value1, void* value2, int attrLength){ 12 | if((*(int *)value1 < *(int *)value2)) 13 | return -1; 14 | else if((*(int *)value1 > *(int *)value2)) 15 | return 1; 16 | else 17 | return 0; 18 | } 19 | 20 | static int compare_float(void *value1, void* value2, int attrLength){ 21 | if((*(float *)value1 < *(float *)value2)) 22 | return -1; 23 | else if((*(float *)value1 > *(float *)value2)) 24 | return 1; 25 | else 26 | return 0; 27 | } 28 | 29 | static bool print_string(void *value, int attrLength){ 30 | char * str = (char *)malloc(attrLength + 1); 31 | memcpy(str, value, attrLength+1); 32 | str[attrLength] = '\0'; 33 | printf("%s ", str); 34 | free(str); 35 | return true; 36 | } 37 | 38 | static bool print_int(void *value, int attrLength){ 39 | int num = *(int*)value; 40 | printf("%d ", num); 41 | return true; 42 | } 43 | 44 | static bool print_float(void *value, int attrLength){ 45 | float num = *(float *)value; 46 | printf("%f ", num); 47 | return true; 48 | } 49 | -------------------------------------------------------------------------------- /src/data.txt: -------------------------------------------------------------------------------- 1 | 1,2,3E-1 2 | 2,3,4E9 3 | 3,4,5E13 4 | -------------------------------------------------------------------------------- /src/dbcreate.cc: -------------------------------------------------------------------------------- 1 | // 2 | // dbcreate.cc 3 | // 4 | // Author: Jason McHugh (mchughj@cs.stanford.edu) 5 | // 6 | // This shell is provided for the student. 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "rm.h" 13 | #include "sm.h" 14 | #include "redbase.h" 15 | #include 16 | 17 | using namespace std; 18 | 19 | //int isDir(const char *file){ 20 | // struct stat buf; 21 | // stat(file, &buf); 22 | // return S_ISREG(buf.st_mode); 23 | //} 24 | 25 | // 26 | // main 27 | // 28 | int main(int argc, char *argv[]) 29 | { 30 | char *dbname; 31 | char command[255] = "mkdir "; 32 | RC rc; 33 | 34 | // Look for 2 arguments. The first is always the name of the program 35 | // that was executed, and the second should be the name of the 36 | // database. 37 | if (argc != 2) { 38 | cerr << "Usage: " << argv[0] << " dbname \n"; 39 | exit(1); 40 | } 41 | 42 | // The database name is the second argument 43 | dbname = argv[1]; 44 | if(strlen(argv[1]) > (sizeof(command)-strlen(command) - 1)){ 45 | cerr << argv[1] << " length exceeds maximum allowed, cannot create database\n"; 46 | exit(1); 47 | } 48 | 49 | // Create a subdirectory for the database 50 | int error = system (strcat(command,dbname)); 51 | 52 | if(error){ 53 | cerr << "system call to create directory exited with error code " << error << endl; 54 | exit(1); 55 | } 56 | 57 | if (chdir(dbname) < 0) { 58 | cerr << argv[0] << " chdir error to " << dbname << "\n"; 59 | exit(1); 60 | } 61 | 62 | // Create the system catalogs... 63 | 64 | PF_Manager pfm; 65 | RM_Manager rmm(pfm); 66 | 67 | // Calculate the size of entries in relcat: 68 | int relCatRecSize = sizeof(RelCatEntry); 69 | int attrCatRecSize = sizeof(AttrCatEntry); 70 | 71 | if((rc = rmm.CreateFile("relcat", relCatRecSize))){ 72 | cerr << "Trouble creating relcat. Exiting" < 9 | #include 10 | #include 11 | #include 12 | #include "rm.h" 13 | #include "sm.h" 14 | #include "redbase.h" 15 | #include 16 | 17 | 18 | using namespace std; 19 | 20 | 21 | // 22 | // main 23 | // 24 | int main(int argc, char *argv[]) 25 | { 26 | char *dbname; 27 | char command[255] = "rm -r "; 28 | RC rc; 29 | 30 | // Look for 2 arguments. The first is always the name of the program 31 | // that was executed, and the second should be the name of the 32 | // database. 33 | if (argc != 2) { 34 | cerr << "Usage: " << argv[0] << " dbname \n"; 35 | exit(1); 36 | } 37 | 38 | // The database name is the second argument 39 | dbname = argv[1]; 40 | if(strlen(argv[1]) > (sizeof(command)-strlen(command) - 1)){ 41 | cerr << argv[1] << " length exceeds maximum allowed, cannot delete database\n"; 42 | exit(1); 43 | } 44 | 45 | // Create a subdirectory for the database 46 | int error = system (strcat(command,dbname)); 47 | 48 | if(error){ 49 | cerr << "system call to destroy directory exited with error code " << error << endl; 50 | exit(1); 51 | } 52 | 53 | /* 54 | if (chdir(dbname) < 0) { 55 | cerr << argv[0] << " chdir error to " << dbname << "\n"; 56 | exit(1); 57 | } 58 | */ 59 | 60 | 61 | return(0); 62 | } 63 | -------------------------------------------------------------------------------- /src/ix_error.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: ix_error.cc 3 | // Description: IX_PrintError functions 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Yifei Huang (yifei@stanford.edu) 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "ix_internal.h" 13 | 14 | using namespace std; 15 | 16 | // 17 | // Error table 18 | // 19 | static char *IX_WarnMsg[] = { 20 | (char*)"bad index specification", 21 | (char*)"bad index name", 22 | (char*)"invalid index handle", 23 | (char*)"invalid index file", 24 | (char*)"page is full", 25 | (char*)"invalid file", 26 | (char*)"invalid bucket number", 27 | (char*)"cannot insert duplicate entry", 28 | (char*)"invalid scan instance", 29 | (char*)"invalid record entry", 30 | (char*)"end of file", 31 | (char*)"IX warning" 32 | }; 33 | 34 | static char *IX_ErrorMsg[] = { 35 | (char*)"IX error" 36 | }; 37 | 38 | // 39 | // RM_PrintError 40 | // 41 | // Desc: Send a message corresponding to a RM return code to cerr 42 | // Assumes PF_UNIX is last valid RM return code 43 | // In: rc - return code for which a message is desired 44 | // 45 | void IX_PrintError(RC rc) 46 | { 47 | // Check the return code is within proper limits 48 | if (rc >= START_IX_WARN && rc <= IX_LASTWARN) 49 | // Print warning 50 | cerr << "IX warning: " << IX_WarnMsg[rc - START_IX_WARN] << "\n"; 51 | // Error codes are negative, so invert everything 52 | else if (-rc >= -START_IX_ERR && -rc < -IX_LASTERROR) 53 | // Print error 54 | cerr << "IX error: " << IX_ErrorMsg[-rc + START_IX_ERR] << "\n"; 55 | else if (rc == PF_UNIX) 56 | #ifdef PC 57 | cerr << "OS error\n"; 58 | #else 59 | cerr << strerror(errno) << "\n"; 60 | #endif 61 | else if (rc == 0) 62 | cerr << "IX_PrintError called with return code of 0\n"; 63 | else 64 | cerr << "IX error: " << rc << " is out of bounds\n"; 65 | } -------------------------------------------------------------------------------- /src/ix_internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // ix_internal.h 3 | // 4 | // Index Manager Component Interface - Internal Structures 5 | // 6 | 7 | #ifndef IX_INTERNAL_H 8 | #define IX_INTERNAL_H 9 | 10 | #include "ix.h" 11 | 12 | #define NO_MORE_PAGES -1 13 | #define NO_MORE_SLOTS -1 14 | 15 | // The following structs define the headers for each node. 16 | // IX_NodeHeader is used as a generic cast for all nodes. 17 | // IX_NodeHeader_I is used once we know the node is an internal node 18 | // IX_NodeHeader_L is used once we know the node is a leaf node 19 | struct IX_NodeHeader{ 20 | bool isLeafNode; // indicator for whether it is a leaf node 21 | bool isEmpty; // Whether the node contains pointers or not 22 | int num_keys; // number of valid keys the node holds 23 | 24 | int firstSlotIndex; // the pointer to the beginning of the linked list of 25 | // valid key/pointer slots 26 | int freeSlotIndex; // the pointer to the beginning of free slots 27 | PageNum invalid1; 28 | PageNum invalid2; 29 | }; 30 | 31 | struct IX_NodeHeader_I{ 32 | bool isLeafNode; 33 | bool isEmpty; // whether the node has its first page pointer 34 | // or not 35 | int num_keys; 36 | 37 | int firstSlotIndex; 38 | int freeSlotIndex; 39 | PageNum firstPage; // first leaf page under this internal node 40 | PageNum invalid2; 41 | }; 42 | 43 | struct IX_NodeHeader_L{ 44 | bool isLeafNode; 45 | bool isEmpty; 46 | int num_keys; 47 | 48 | int firstSlotIndex; 49 | int freeSlotIndex; 50 | PageNum nextPage; // next leaf page 51 | PageNum prevPage; // previous leaf page 52 | }; 53 | 54 | // This is the header for the bucket pages 55 | struct IX_BucketHeader{ 56 | int num_keys; // number of entries in the bucket 57 | int firstSlotIndex; // pointer to the first valid slot in the bucket 58 | int freeSlotIndex; // pointer to the first free slot in bucket 59 | PageNum nextBucket; // pointer to the next bucket page (in case of 60 | // overflow, i.e. lots of duplicates) 61 | }; 62 | 63 | 64 | // The following are "entries", or the headers that provide 65 | // information about each slot 66 | struct Entry{ 67 | char isValid; 68 | int nextSlot; 69 | }; 70 | 71 | struct Node_Entry{ 72 | char isValid; // Whether the slot is valid, contains a duplicate 73 | // value, or a single value 74 | int nextSlot; // Pointer to the next slot in the node 75 | PageNum page; // Pointer to the page associated with this key 76 | SlotNum slot; // Pointer to the slot associated with this entry 77 | // (only valid for leaf nodes) 78 | }; 79 | 80 | // All entries in the bucket will be duplicates of the same value, 81 | // So we don't have to worry about the isValid flag 82 | struct Bucket_Entry{ 83 | int nextSlot; // Pointer to the next slot 84 | PageNum page; // Page of record 85 | SlotNum slot; // slot of record 86 | }; 87 | 88 | 89 | 90 | #endif -------------------------------------------------------------------------------- /src/node.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: node.cc 3 | // Description: Abstract class for query processing nodes 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | 18 | using namespace std; 19 | 20 | QL_Node::QL_Node(){ 21 | 22 | } 23 | 24 | QL_Node::~QL_Node(){ 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/node_comps.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "pf.h" 4 | #include 5 | #include 6 | /* 7 | * The following functions are comparison functions that return 0 if 8 | * the two objects are equal, <0 if the first value is smaller, and 9 | * >0 if the second value is smaller. 10 | * They must take in an attribute type and attribute length, which 11 | * determines the basis to compare the values on. 12 | */ 13 | bool nequal(void * value1, void * value2, AttrType attrtype, int attrLength){ 14 | switch(attrtype){ 15 | case FLOAT: return (*(float *)value1 == *(float*)value2); 16 | case INT: return (*(int *)value1 == *(int *)value2) ; 17 | default: 18 | return (strncmp((char *) value1, (char *) value2, attrLength) == 0); 19 | } 20 | } 21 | 22 | bool nless_than(void * value1, void * value2, AttrType attrtype, int attrLength){ 23 | switch(attrtype){ 24 | case FLOAT: return (*(float *)value1 < *(float*)value2); 25 | case INT: return (*(int *)value1 < *(int *)value2) ; 26 | default: 27 | return (strncmp((char *) value1, (char *) value2, attrLength) < 0); 28 | } 29 | } 30 | 31 | bool ngreater_than(void * value1, void * value2, AttrType attrtype, int attrLength){ 32 | switch(attrtype){ 33 | case FLOAT: return (*(float *)value1 > *(float*)value2); 34 | case INT: return (*(int *)value1 > *(int *)value2) ; 35 | default: 36 | return (strncmp((char *) value1, (char *) value2, attrLength) > 0); 37 | } 38 | } 39 | 40 | bool nless_than_or_eq_to(void * value1, void * value2, AttrType attrtype, int attrLength){ 41 | switch(attrtype){ 42 | case FLOAT: return (*(float *)value1 <= *(float*)value2); 43 | case INT: return (*(int *)value1 <= *(int *)value2) ; 44 | default: 45 | return (strncmp((char *) value1, (char *) value2, attrLength) <= 0); 46 | } 47 | } 48 | 49 | bool ngreater_than_or_eq_to(void * value1, void * value2, AttrType attrtype, int attrLength){ 50 | switch(attrtype){ 51 | case FLOAT: return (*(float *)value1 >= *(float*)value2); 52 | case INT: return (*(int *)value1 >= *(int *)value2) ; 53 | default: 54 | return (strncmp((char *) value1, (char *) value2, attrLength) >= 0); 55 | } 56 | } 57 | 58 | bool nnot_equal(void * value1, void * value2, AttrType attrtype, int attrLength){ 59 | switch(attrtype){ 60 | case FLOAT: return (*(float *)value1 != *(float*)value2); 61 | case INT: return (*(int *)value1 != *(int *)value2) ; 62 | default: 63 | return (strncmp((char *) value1, (char *) value2, attrLength) != 0); 64 | } 65 | } -------------------------------------------------------------------------------- /src/node_proj.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: node_proj.cc 3 | // Description: Node for projection processing 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | 18 | using namespace std; 19 | 20 | Node_Proj::Node_Proj(){ 21 | 22 | } 23 | 24 | Node_Proj::~Node_Proj(){ 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/node_rel.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: node_rel.cc 3 | // Description: Node for relation processing 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | #include "node_comps.h" 18 | 19 | 20 | using namespace std; 21 | 22 | 23 | Node_Rel::Node_Rel(QL_Manager &qlm, RelCatEntry* rEntry) : QL_Node(qlm) { 24 | relName = (char *)malloc(MAXNAME+1); 25 | memset((void *)relName, 0, sizeof(relName)); 26 | memcpy(this->relName, rEntry->relName, strlen(rEntry->relName) + 1); 27 | tupleLength = rEntry->tupleLength; 28 | isOpen = false; 29 | listsInitialized = false; 30 | relNameInitialized = true; 31 | useIndex = false; 32 | condIndex = 0; 33 | indexNo = 0; 34 | } 35 | 36 | Node_Rel::~Node_Rel(){ 37 | if(listsInitialized == true){ 38 | free(attrsInRec); 39 | free(condList); 40 | } 41 | if(relNameInitialized == true){ 42 | free(relName); 43 | } 44 | } 45 | 46 | RC Node_Rel::SetUpRel(int *attrs, int attrlistSize, int numConds){ 47 | attrsInRecSize = attrlistSize; 48 | attrsInRec = (int*)malloc(attrlistSize*sizeof(int)); 49 | memset((void *)attrsInRec, 0, sizeof(attrsInRec)); 50 | for(int i = 0; i < attrlistSize; i++){ 51 | attrsInRec[i] = attrs[i]; 52 | } 53 | condList = (Cond *)malloc(numConds * sizeof(Cond)); 54 | for(int i= 0; i < numConds; i++){ 55 | condList[i] = {0, NULL, true, NULL, 0, 0, INT}; 56 | } 57 | listsInitialized = true; 58 | 59 | return (0); 60 | } 61 | 62 | /* 63 | RC Node_Rel::AddCondition(const Condition condition){ 64 | RC rc = 0; 65 | int index1, index2; 66 | int offset1, offset2; 67 | int length1, length2; 68 | if((rc = qlm.GetAttrCatEntryPos(condition.lhsAttr, index1) ) || (rc = QL_Node::IndexToOffset(index1, offset1, length1))) 69 | return (rc); 70 | condList[condIndex].offset1 = offset1; 71 | condList[condIndex].length = length1; 72 | condList[condIndex].type = qlm.attrEntries[index1].attrType; 73 | 74 | if(condition.bRhsIsAttr){ 75 | if((rc = qlm.GetAttrCatEntryPos(condition.rhsAttr, index2)) || (rc = QL_Node::IndexToOffset(index2, offset2, length2))) 76 | return (rc); 77 | condList[condIndex].offset2 = offset2; 78 | condList[condIndex].isValue = false; 79 | if(length2 < condList[condIndex].length) 80 | condList[condIndex].length = length2; 81 | } 82 | else{ 83 | condList[condIndex].isValue = true; 84 | condList[condIndex].data = condition.rhsValue.data; 85 | } 86 | 87 | switch(condition.op){ 88 | case EQ_OP : condList[condIndex].comparator = &nequal; break; 89 | case LT_OP : condList[condIndex].comparator = &nless_than; break; 90 | case GT_OP : condList[condIndex].comparator = &ngreater_than; break; 91 | case LE_OP : condList[condIndex].comparator = &nless_than_or_eq_to; break; 92 | case GE_OP : condList[condIndex].comparator = &ngreater_than_or_eq_to; break; 93 | case NE_OP : condList[condIndex].comparator = &nnot_equal; break; 94 | default: return (QL_BADCOND); 95 | } 96 | 97 | if(condition.op == EQ_OP && !condition.bRhsIsAttr && useIndex == false 98 | && qlm.attrEntries[index1].indexNo != -1){ 99 | useIndex = true; 100 | eqCond.offset1 = condList[condIndex].offset1; 101 | eqCond.comparator = condList[condIndex].comparator; 102 | eqCond.isValue = condList[condIndex].isValue; 103 | eqCond.data = condList[condIndex].data; 104 | eqCond.offset2 = condList[condIndex].offset2; 105 | eqCond.length = condList[condIndex].length; 106 | eqCond.type = condList[condIndex].type; 107 | indexNo = qlm.attrEntries[index1].indexNo; 108 | } 109 | else{ 110 | condIndex++; 111 | } 112 | 113 | return (0); 114 | 115 | }*/ 116 | 117 | RC Node_Rel::OpenIt(){ 118 | RC rc = 0; 119 | isOpen = true; 120 | if(useIndex){ 121 | if((rc = qlm.ixm.OpenIndex(relName, indexNo, ih))) 122 | return (rc); 123 | if((rc = is.OpenScan(ih, EQ_OP, eqCond.data))) 124 | return (rc); 125 | if((rc = qlm.rmm.OpenFile(relName, fh))) 126 | return (rc); 127 | } 128 | else{ 129 | if((rc = qlm.rmm.OpenFile(relName, fh))) 130 | return (rc); 131 | if((rc = fs.OpenScan(fh, INT, 4, 0, NO_OP, NULL))) 132 | return (rc); 133 | 134 | } 135 | return (0); 136 | } 137 | 138 | RC Node_Rel::GetNext(char * data){ 139 | RC rc = 0; 140 | char * recData; 141 | RM_Record rec; 142 | while(true){ 143 | if((rc = GetNextRecData(rec, recData) )) 144 | return (rc); 145 | 146 | RC cond = CheckConditions(recData); 147 | if(cond == 0) 148 | break; 149 | } 150 | 151 | memcpy(data, recData, tupleLength); 152 | return (0); 153 | } 154 | 155 | RC Node_Rel::GetNextRec(RM_Record &rec){ 156 | RC rc = 0; 157 | char * recData; 158 | while(true){ 159 | if((rc = GetNextRecData(rec, recData) )) 160 | return (rc); 161 | 162 | RC cond = CheckConditions(recData); 163 | if(cond == 0) 164 | break; 165 | } 166 | return (0); 167 | } 168 | 169 | 170 | RC Node_Rel::CheckConditions(char *recData){ 171 | RC rc = 0; 172 | for(int i = 0; i < condIndex; i++){ 173 | int offset1 = condList[i].offset1; 174 | if(! condList[i].isValue){ 175 | int offset2 = condList[i].offset2; 176 | bool comp = condList[i].comparator((void *)(recData + offset1), (void *)(recData + offset2), 177 | condList[i].type, condList[i].length); 178 | if(comp == false) 179 | return (-1); 180 | } 181 | else{ 182 | bool comp = condList[i].comparator((void *)(recData + offset1), condList[i].data, 183 | condList[i].type, condList[i].length); 184 | if(comp == false) 185 | return (-1); 186 | } 187 | 188 | } 189 | 190 | return (0); 191 | } 192 | 193 | RC Node_Rel::CloseIt(){ 194 | RC rc = 0; 195 | if(useIndex){ 196 | if((rc = qlm.rmm.CloseFile(fh))) 197 | return (rc); 198 | if((rc = is.CloseScan())) 199 | return (rc); 200 | if((rc = qlm.ixm.CloseIndex(ih ))) 201 | return (rc); 202 | } 203 | else{ 204 | if((rc = fs.CloseScan()) || (rc = qlm.rmm.CloseFile(fh))) 205 | return (rc); 206 | } 207 | isOpen = false; 208 | return (0); 209 | } 210 | 211 | RC Node_Rel::GetNextRecData(RM_Record &rec, char *&recData){ 212 | RC rc = 0; 213 | if(useIndex){ 214 | RID rid; 215 | if((rc = is.GetNextEntry(rid) )) 216 | return (rc); 217 | if((rc = fh.GetRec(rid, rec) )) 218 | return (rc); 219 | } 220 | else{ 221 | if((rc = fs.GetNextRec(rec))) 222 | return (rc); 223 | } 224 | if((rc = rec.GetData(recData))) 225 | return (rc); 226 | return (0); 227 | } 228 | 229 | RC Node_Rel::PrintNode(int numTabs){ 230 | return (0); 231 | } 232 | 233 | /* 234 | RC Node_Rel::IndexToOffset(int index, int &offset, int &length){ 235 | offset = 0; 236 | for(int i=0; i < attrsInRecSize; i++){ 237 | if(attrsInRec[i] == index){ 238 | length = qlm.attrEntries[attrsInRec[i]].attrLength; 239 | return (0); 240 | } 241 | offset += qlm.attrEntries[attrsInRec[i]].attrLength; 242 | } 243 | return (QL_ATTRNOTFOUND); 244 | } 245 | */ 246 | 247 | RC Node_Rel::DeleteNodes(){ 248 | // This relation has nothing to destroy 249 | if(listsInitialized == true){ 250 | free(attrsInRec); 251 | free(condList); 252 | } 253 | listsInitialized = false; 254 | if(relNameInitialized == true){ 255 | free(relName); 256 | } 257 | relNameInitialized = false; 258 | return (0); 259 | } 260 | 261 | /* 262 | 263 | RC Node_Rel::GetAttrList(int *attrList, int &attrListSize){ 264 | attrList = attrsInRec; 265 | attrListSize = attrsInRecSize; 266 | return (0); 267 | } 268 | 269 | RC Node_Rel::GetTupleLength(int &tupleLength){ 270 | tupleLength = this->tupleLength; 271 | return (0); 272 | } 273 | */ 274 | 275 | -------------------------------------------------------------------------------- /src/node_sel.cc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yifeih/redbase/97560d7d4a74ea5ad4be928422144d76bf7ed148/src/node_sel.cc -------------------------------------------------------------------------------- /src/parser.h: -------------------------------------------------------------------------------- 1 | // 2 | // parser.h 3 | // Parser Component Interface 4 | // 5 | 6 | #ifndef PARSER_H 7 | #define PARSER_H 8 | 9 | #include 10 | #include "redbase.h" 11 | #include "pf.h" 12 | 13 | // 14 | // Structure declarations and output functions 15 | // 16 | struct AttrInfo{ 17 | char *attrName; /* attribute name */ 18 | AttrType attrType; /* type of attribute */ 19 | int attrLength; /* length of attribute */ 20 | }; 21 | 22 | struct RelAttr{ 23 | char *relName; // Relation name (may be NULL) 24 | char *attrName; // Attribute name 25 | 26 | // Print function 27 | friend std::ostream &operator<<(std::ostream &s, const RelAttr &ra); 28 | }; 29 | 30 | struct Value{ 31 | AttrType type; /* type of value */ 32 | void *data; /* value */ 33 | /* print function */ 34 | friend std::ostream &operator<<(std::ostream &s, const Value &v); 35 | }; 36 | 37 | struct Condition{ 38 | RelAttr lhsAttr; /* left-hand side attribute */ 39 | CompOp op; /* comparison operator */ 40 | int bRhsIsAttr; /* TRUE if the rhs is an attribute, */ 41 | /* in which case rhsAttr below is valid;*/ 42 | /* otherwise, rhsValue below is valid. */ 43 | RelAttr rhsAttr; /* right-hand side attribute */ 44 | Value rhsValue; /* right-hand side value */ 45 | /* print function */ 46 | friend std::ostream &operator<<(std::ostream &s, const Condition &c); 47 | 48 | }; 49 | 50 | std::ostream &operator<<(std::ostream &s, const CompOp &op); 51 | std::ostream &operator<<(std::ostream &s, const AttrType &at); 52 | 53 | // 54 | // Parse function 55 | // 56 | class QL_Manager; 57 | class SM_Manager; 58 | 59 | void RBparse(PF_Manager &pfm, SM_Manager &smm, QL_Manager &qlm); 60 | 61 | // 62 | // Error printing function; calls component-specific functions 63 | // 64 | void PrintError(RC rc); 65 | 66 | // bQueryPlans is allocated by parse.y. When bQueryPlans is 1 then the 67 | // query plan chosen for the SFW query will be displayed. When 68 | // bQueryPlans is 0 then no query plan is shown. 69 | extern int bQueryPlans; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/parser_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * parser_internal.h: internal declarations for the REDBASE parser 3 | * 4 | * Authors: Dallan Quass 5 | * Jan Jannink 6 | * 7 | * originally by: Mark McAuliffe, University of Wisconsin - Madison, 1991 8 | */ 9 | 10 | #ifndef PARSER_INTERNAL_H 11 | #define PARSER_INTERNAL_H 12 | 13 | #include "parser.h" 14 | 15 | /* 16 | * use double for real 17 | */ 18 | typedef float real; 19 | 20 | /* 21 | * the prompt 22 | */ 23 | #define PROMPT "\nREDBASE >> " 24 | 25 | /* 26 | * REL_ATTR: describes a qualified attribute (relName.attrName) 27 | */ 28 | typedef struct{ 29 | char *relName; /* relation name */ 30 | char *attrName; /* attribute name */ 31 | } REL_ATTR; 32 | 33 | /* 34 | * ATTR_VAL: pair 35 | */ 36 | typedef struct{ 37 | char *attrName; /* attribute name */ 38 | AttrType valType; /* type of value */ 39 | int valLength; /* length if type = STRING */ 40 | void *value; /* value for attribute */ 41 | } ATTR_VAL; 42 | 43 | /* 44 | * all the available kinds of nodes 45 | */ 46 | typedef enum{ 47 | N_CREATETABLE, 48 | N_CREATEINDEX, 49 | N_DROPTABLE, 50 | N_DROPINDEX, 51 | N_LOAD, 52 | N_SET, 53 | N_HELP, 54 | N_PRINT, 55 | N_QUERY, 56 | N_INSERT, 57 | N_DELETE, 58 | N_UPDATE, 59 | N_RELATTR, 60 | N_CONDITION, 61 | N_RELATTR_OR_VALUE, 62 | N_ATTRTYPE, 63 | N_VALUE, 64 | N_RELATION, 65 | N_STATISTICS, 66 | N_LIST 67 | } NODEKIND; 68 | 69 | /* 70 | * structure of parse tree nodes 71 | */ 72 | typedef struct node{ 73 | NODEKIND kind; 74 | 75 | union{ 76 | /* SM component nodes */ 77 | /* create table node */ 78 | struct{ 79 | char *relname; 80 | struct node *attrlist; 81 | } CREATETABLE; 82 | 83 | /* create index node */ 84 | struct{ 85 | char *relname; 86 | char *attrname; 87 | } CREATEINDEX; 88 | 89 | /* drop index node */ 90 | struct{ 91 | char *relname; 92 | char *attrname; 93 | } DROPINDEX; 94 | 95 | /* drop table node */ 96 | struct{ 97 | char *relname; 98 | } DROPTABLE; 99 | 100 | /* load node */ 101 | struct{ 102 | char *relname; 103 | char *filename; 104 | } LOAD; 105 | 106 | /* set node */ 107 | struct{ 108 | char *paramName; 109 | char *string; 110 | } SET; 111 | 112 | /* help node */ 113 | struct{ 114 | char *relname; 115 | } HELP; 116 | 117 | /* print node */ 118 | struct{ 119 | char *relname; 120 | } PRINT; 121 | 122 | /* QL component nodes */ 123 | /* query node */ 124 | struct{ 125 | struct node *relattrlist; 126 | struct node *rellist; 127 | struct node *conditionlist; 128 | } QUERY; 129 | 130 | /* insert node */ 131 | struct{ 132 | char *relname; 133 | struct node *valuelist; 134 | } INSERT; 135 | 136 | /* delete node */ 137 | struct{ 138 | char *relname; 139 | struct node *conditionlist; 140 | } DELETE; 141 | 142 | /* update node */ 143 | struct{ 144 | char *relname; 145 | struct node *relattr; 146 | struct node *relorvalue; 147 | struct node *conditionlist; 148 | } UPDATE; 149 | 150 | /* command support nodes */ 151 | /* relation attribute node */ 152 | struct{ 153 | char *relname; 154 | char *attrname; 155 | } RELATTR; 156 | 157 | /* condition node */ 158 | struct{ 159 | struct node *lhsRelattr; 160 | CompOp op; 161 | struct node *rhsRelattr; 162 | struct node *rhsValue; 163 | } CONDITION; 164 | 165 | /* relation-attribute or value */ 166 | struct{ 167 | struct node *relattr; 168 | struct node *value; 169 | } RELATTR_OR_VALUE; 170 | 171 | /* pair */ 172 | struct{ 173 | char *attrname; 174 | char *type; 175 | } ATTRTYPE; 176 | 177 | /* pair */ 178 | struct{ 179 | AttrType type; 180 | int ival; 181 | real rval; 182 | char *sval; 183 | } VALUE; 184 | 185 | /* relation node */ 186 | struct{ 187 | char *relname; 188 | } RELATION; 189 | 190 | /* list node */ 191 | struct{ 192 | struct node *curr; 193 | struct node *next; 194 | } LIST; 195 | } u; 196 | } NODE; 197 | 198 | 199 | /* 200 | * function prototypes 201 | */ 202 | NODE *newnode(NODEKIND kind); 203 | NODE *create_table_node(char *relname, NODE *attrlist); 204 | NODE *create_index_node(char *relname, char *attrname); 205 | NODE *drop_index_node(char *relname, char *attrname); 206 | NODE *drop_table_node(char *relname); 207 | NODE *load_node(char *relname, char *filename); 208 | NODE *set_node(char *paramName, char *string); 209 | NODE *help_node(char *relname); 210 | NODE *print_node(char *relname); 211 | NODE *query_node(NODE *relattrlist, NODE *rellist, NODE *conditionlist); 212 | NODE *insert_node(char *relname, NODE *valuelist); 213 | NODE *delete_node(char *relname, NODE *conditionlist); 214 | NODE *update_node(char *relname, NODE *relattr, NODE *value, 215 | NODE *conditionlist); 216 | NODE *relattr_node(char *relname, char *attrname); 217 | NODE *condition_node(NODE *lhsRelattr, CompOp op, NODE *rhsRelattrOrValue); 218 | NODE *value_node(AttrType type, void *value); 219 | NODE *relattr_or_value_node(NODE *relattr, NODE *value); 220 | NODE *attrtype_node(char *attrname, char *type); 221 | NODE *relation_node(char *relname); 222 | NODE *list_node(NODE *n); 223 | NODE *prepend(NODE *n, NODE *list); 224 | 225 | void reset_scanner(void); 226 | void reset_charptr(void); 227 | void new_query(void); 228 | RC interp(NODE *n); 229 | int yylex(void); 230 | int yyparse(void); 231 | 232 | #endif 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /src/parser_test.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: parser_test.cc 3 | // Description: Test the parser 4 | // Authors: Dallan Quass (quass@cs.stanford.edu) 5 | // Jason McHugh (mchughj@cs.stanford.edu) 6 | // 7 | // 1997: Changes for the statistics manager 8 | // 9 | 10 | #include 11 | #include 12 | #include "redbase.h" 13 | #include "parser.h" 14 | #include "sm.h" 15 | #include "ql.h" 16 | 17 | 18 | // 19 | // Global PF_Manager and RM_Manager variables 20 | // 21 | PF_Manager pfm; 22 | RM_Manager rmm(pfm); 23 | IX_Manager ixm(pfm); 24 | SM_Manager smm(ixm, rmm); 25 | QL_Manager qlm(smm, ixm, rmm); 26 | 27 | int main(void) 28 | { 29 | RC rc; 30 | 31 | if ((rc = smm.OpenDb("testdb"))) { 32 | PrintError(rc); 33 | return (1); 34 | } 35 | 36 | RBparse(pfm, smm, qlm); 37 | 38 | if ((rc = smm.CloseDb())) { 39 | PrintError(rc); 40 | return (1); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/pf.h: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf.h 3 | // Description: Paged File component interface 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Jason McHugh (mchughj@cs.stanford.edu) 7 | // 8 | // 1997: Default page size is now 4k. 9 | // Some additional constants used for the statistics. 10 | // 1998: PageNum is now an int instead of short int. 11 | // Allow chunks from the buffer manager to not be associated with 12 | // a particular file. Allows students to use main memory chunks 13 | // that are associated with (and limited by) the buffer. 14 | // 2005: Added GetLastPage and GetPrevPage for rocking 15 | 16 | #ifndef PF_H 17 | #define PF_H 18 | 19 | #include "redbase.h" 20 | 21 | // 22 | // PageNum: uniquely identifies a page in a file 23 | // 24 | typedef int PageNum; 25 | 26 | // Page Size 27 | // 28 | // Each page stores some header information. The PF_PageHdr is defined 29 | // in pf_internal.h and contains the information that we would store. 30 | // Unfortunately, we cannot use sizeof(PF_PageHdr) here, but it is an 31 | // int and we simply use that. 32 | // 33 | const int PF_PAGE_SIZE = 4096 - sizeof(int); 34 | 35 | // 36 | // PF_PageHandle: PF page interface 37 | // 38 | class PF_PageHandle { 39 | friend class PF_FileHandle; 40 | public: 41 | PF_PageHandle (); // Default constructor 42 | ~PF_PageHandle (); // Destructor 43 | 44 | // Copy constructor 45 | PF_PageHandle (const PF_PageHandle &pageHandle); 46 | // Overloaded = 47 | PF_PageHandle& operator=(const PF_PageHandle &pageHandle); 48 | 49 | RC GetData (char *&pData) const; // Set pData to point to 50 | // the page contents 51 | RC GetPageNum (PageNum &pageNum) const; // Return the page number 52 | private: 53 | int pageNum; // page number 54 | char *pPageData; // pointer to page data 55 | }; 56 | 57 | // 58 | // PF_FileHdr: Header structure for files 59 | // 60 | struct PF_FileHdr { 61 | int firstFree; // first free page in the linked list 62 | int numPages; // # of pages in the file 63 | }; 64 | 65 | // 66 | // PF_FileHandle: PF File interface 67 | // 68 | class PF_BufferMgr; 69 | 70 | class PF_FileHandle { 71 | friend class PF_Manager; 72 | public: 73 | PF_FileHandle (); // Default constructor 74 | ~PF_FileHandle (); // Destructor 75 | 76 | // Copy constructor 77 | PF_FileHandle (const PF_FileHandle &fileHandle); 78 | 79 | // Overload = 80 | PF_FileHandle& operator=(const PF_FileHandle &fileHandle); 81 | 82 | // Get the first page 83 | RC GetFirstPage(PF_PageHandle &pageHandle) const; 84 | // Get the next page after current 85 | RC GetNextPage (PageNum current, PF_PageHandle &pageHandle) const; 86 | // Get a specific page 87 | RC GetThisPage (PageNum pageNum, PF_PageHandle &pageHandle) const; 88 | // Get the last page 89 | RC GetLastPage(PF_PageHandle &pageHandle) const; 90 | // Get the prev page after current 91 | RC GetPrevPage (PageNum current, PF_PageHandle &pageHandle) const; 92 | 93 | RC AllocatePage(PF_PageHandle &pageHandle); // Allocate a new page 94 | RC DisposePage (PageNum pageNum); // Dispose of a page 95 | RC MarkDirty (PageNum pageNum) const; // Mark page as dirty 96 | RC UnpinPage (PageNum pageNum) const; // Unpin the page 97 | 98 | // Flush pages from buffer pool. Will write dirty pages to disk. 99 | RC FlushPages () const; 100 | 101 | // Force a page or pages to disk (but do not remove from the buffer pool) 102 | RC ForcePages (PageNum pageNum=ALL_PAGES) const; 103 | 104 | private: 105 | 106 | // IsValidPageNum will return TRUE if page number is valid and FALSE 107 | // otherwise 108 | int IsValidPageNum (PageNum pageNum) const; 109 | 110 | PF_BufferMgr *pBufferMgr; // pointer to buffer manager 111 | PF_FileHdr hdr; // file header 112 | int bFileOpen; // file open flag 113 | int bHdrChanged; // dirty flag for file hdr 114 | int unixfd; // OS file descriptor 115 | }; 116 | 117 | // 118 | // PF_Manager: provides PF file management 119 | // 120 | class PF_Manager { 121 | public: 122 | PF_Manager (); // Constructor 123 | ~PF_Manager (); // Destructor 124 | RC CreateFile (const char *fileName); // Create a new file 125 | RC DestroyFile (const char *fileName); // Delete a file 126 | 127 | // Open and close file methods 128 | RC OpenFile (const char *fileName, PF_FileHandle &fileHandle); 129 | RC CloseFile (PF_FileHandle &fileHandle); 130 | 131 | // Three methods that manipulate the buffer manager. The calls are 132 | // forwarded to the PF_BufferMgr instance and are called by parse.y 133 | // when the user types in a system command. 134 | RC ClearBuffer (); 135 | RC PrintBuffer (); 136 | RC ResizeBuffer (int iNewSize); 137 | 138 | // Three Methods for manipulating raw memory buffers. These memory 139 | // locations are handled by the buffer manager, but are not 140 | // associated with a particular file. These should be used if you 141 | // want to create structures in memory that are bounded by the size 142 | // of the buffer pool. 143 | // 144 | // Note: If you lose the pointer to the buffer that is passed back 145 | // from AllocateBlock or do not call DisposeBlock with that pointer 146 | // then the internal memory will always remain "pinned" in the buffer 147 | // pool and you will have lost a slot in the buffer pool. 148 | 149 | // Return the size of the block that can be allocated. 150 | RC GetBlockSize (int &length) const; 151 | 152 | // Allocate a memory chunk that lives in buffer manager 153 | RC AllocateBlock (char *&buffer); 154 | // Dispose of a memory chunk managed by the buffer manager. 155 | RC DisposeBlock (char *buffer); 156 | 157 | private: 158 | PF_BufferMgr *pBufferMgr; // page-buffer manager 159 | }; 160 | 161 | // 162 | // Print-error function and PF return code defines 163 | // 164 | void PF_PrintError(RC rc); 165 | 166 | #define PF_PAGEPINNED (START_PF_WARN + 0) // page pinned in buffer 167 | #define PF_PAGENOTINBUF (START_PF_WARN + 1) // page isn't pinned in buffer 168 | #define PF_INVALIDPAGE (START_PF_WARN + 2) // invalid page number 169 | #define PF_FILEOPEN (START_PF_WARN + 3) // file is open 170 | #define PF_CLOSEDFILE (START_PF_WARN + 4) // file is closed 171 | #define PF_PAGEFREE (START_PF_WARN + 5) // page already free 172 | #define PF_PAGEUNPINNED (START_PF_WARN + 6) // page already unpinned 173 | #define PF_EOF (START_PF_WARN + 7) // end of file 174 | #define PF_TOOSMALL (START_PF_WARN + 8) // Resize buffer too small 175 | #define PF_LASTWARN PF_TOOSMALL 176 | 177 | #define PF_NOMEM (START_PF_ERR - 0) // no memory 178 | #define PF_NOBUF (START_PF_ERR - 1) // no buffer space 179 | #define PF_INCOMPLETEREAD (START_PF_ERR - 2) // incomplete read from file 180 | #define PF_INCOMPLETEWRITE (START_PF_ERR - 3) // incomplete write to file 181 | #define PF_HDRREAD (START_PF_ERR - 4) // incomplete read of header 182 | #define PF_HDRWRITE (START_PF_ERR - 5) // incomplete write to header 183 | 184 | // Internal errors 185 | #define PF_PAGEINBUF (START_PF_ERR - 6) // new page already in buffer 186 | #define PF_HASHNOTFOUND (START_PF_ERR - 7) // hash table entry not found 187 | #define PF_HASHPAGEEXIST (START_PF_ERR - 8) // page already in hash table 188 | #define PF_INVALIDNAME (START_PF_ERR - 9) // invalid PC file name 189 | 190 | // Error in UNIX system call or library routine 191 | #define PF_UNIX (START_PF_ERR - 10) // Unix error 192 | #define PF_LASTERROR PF_UNIX 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/pf_buffermgr.h: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_buffermgr.h 3 | // Description: PF_BufferMgr class interface 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Jason McHugh (mchughj@cs.stanford.edu) 7 | // 8 | // 1997: When requesting a page from the buffer manager the page requested 9 | // is now promoted to the MRU slot. 10 | // 1998: Allow chunks from the buffer manager to not be associated with 11 | // a particular file. Allows students to use main memory chunks that 12 | // are associated with (and limited by) the buffer. 13 | // 14 | 15 | #ifndef PF_BUFFERMGR_H 16 | #define PF_BUFFERMGR_H 17 | 18 | #include "pf_internal.h" 19 | #include "pf_hashtable.h" 20 | 21 | // 22 | // Defines 23 | // 24 | 25 | // INVALID_SLOT is used within the PF_BufferMgr class which tracks a list 26 | // of PF_BufPageDesc. Inside the PF_BufPageDesc are integer "pointers" to 27 | // next and prev items. INVALID_SLOT is used to indicate no previous or 28 | // next. 29 | #define INVALID_SLOT (-1) 30 | 31 | // 32 | // PF_BufPageDesc - struct containing data about a page in the buffer 33 | // 34 | struct PF_BufPageDesc { 35 | char *pData; // page contents 36 | int next; // next in the linked list of buffer pages 37 | int prev; // prev in the linked list of buffer pages 38 | int bDirty; // TRUE if page is dirty 39 | short int pinCount; // pin count 40 | PageNum pageNum; // page number for this page 41 | int fd; // OS file descriptor of this page 42 | }; 43 | 44 | // 45 | // PF_BufferMgr - manage the page buffer 46 | // 47 | class PF_BufferMgr { 48 | public: 49 | 50 | PF_BufferMgr (int numPages); // Constructor - allocate 51 | // numPages buffer pages 52 | ~PF_BufferMgr (); // Destructor 53 | 54 | // Read pageNum into buffer, point *ppBuffer to location 55 | RC GetPage (int fd, PageNum pageNum, char **ppBuffer, 56 | int bMultiplePins = TRUE); 57 | // Allocate a new page in the buffer, point *ppBuffer to its location 58 | RC AllocatePage (int fd, PageNum pageNum, char **ppBuffer); 59 | 60 | RC MarkDirty (int fd, PageNum pageNum); // Mark page dirty 61 | RC UnpinPage (int fd, PageNum pageNum); // Unpin page from the buffer 62 | RC FlushPages (int fd); // Flush pages for file 63 | 64 | // Force a page to the disk, but do not remove from the buffer pool 65 | RC ForcePages (int fd, PageNum pageNum); 66 | 67 | 68 | // Remove all entries from the Buffer Manager. 69 | RC ClearBuffer (); 70 | // Display all entries in the buffer 71 | RC PrintBuffer (); 72 | 73 | // Attempts to resize the buffer to the new size 74 | RC ResizeBuffer (int iNewSize); 75 | 76 | // Three Methods for manipulating raw memory buffers. These memory 77 | // locations are handled by the buffer manager, but are not 78 | // associated with a particular file. These should be used if you 79 | // want memory that is bounded by the size of the buffer pool. 80 | 81 | // Return the size of the block that can be allocated. 82 | RC GetBlockSize (int &length) const; 83 | 84 | // Allocate a memory chunk that lives in buffer manager 85 | RC AllocateBlock (char *&buffer); 86 | // Dispose of a memory chunk managed by the buffer manager. 87 | RC DisposeBlock (char *buffer); 88 | 89 | private: 90 | RC InsertFree (int slot); // Insert slot at head of free 91 | RC LinkHead (int slot); // Insert slot at head of used 92 | RC Unlink (int slot); // Unlink slot 93 | RC InternalAlloc(int &slot); // Get a slot to use 94 | 95 | // Read a page 96 | RC ReadPage (int fd, PageNum pageNum, char *dest); 97 | 98 | // Write a page 99 | RC WritePage (int fd, PageNum pageNum, char *source); 100 | 101 | // Init the page desc entry 102 | RC InitPageDesc (int fd, PageNum pageNum, int slot); 103 | 104 | PF_BufPageDesc *bufTable; // info on buffer pages 105 | PF_HashTable hashTable; // Hash table object 106 | int numPages; // # of pages in the buffer 107 | int pageSize; // Size of pages in the buffer 108 | int first; // MRU page slot 109 | int last; // LRU page slot 110 | int free; // head of free list 111 | }; 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/pf_error.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_error.cc 3 | // Description: PF_PrintError function 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include "pf_internal.h" 12 | 13 | using namespace std; 14 | 15 | // 16 | // Error table 17 | // 18 | static char *PF_WarnMsg[] = { 19 | (char*)"page pinned in buffer", 20 | (char*)"page is not in the buffer", 21 | (char*)"invalid page number", 22 | (char*)"file open", 23 | (char*)"invalid file descriptor (file closed)", 24 | (char*)"page already free", 25 | (char*)"page already unpinned", 26 | (char*)"end of file", 27 | (char*)"attempting to resize the buffer too small", 28 | (char*)"invalid filename" 29 | }; 30 | 31 | static char *PF_ErrorMsg[] = { 32 | (char*)"no memory", 33 | (char*)"no buffer space", 34 | (char*)"incomplete read of page from file", 35 | (char*)"incomplete write of page to file", 36 | (char*)"incomplete read of header from file", 37 | (char*)"incomplete write of header from file", 38 | (char*)"new page to be allocated already in buffer", 39 | (char*)"hash table entry not found", 40 | (char*)"page already in hash table", 41 | (char*)"invalid file name" 42 | }; 43 | 44 | // 45 | // PF_PrintError 46 | // 47 | // Desc: Send a message corresponding to a PF return code to cerr 48 | // Assumes PF_UNIX is last valid PF return code 49 | // In: rc - return code for which a message is desired 50 | // 51 | void PF_PrintError(RC rc) 52 | { 53 | // Check the return code is within proper limits 54 | if (rc >= START_PF_WARN && rc <= PF_LASTWARN) 55 | // Print warning 56 | cerr << "PF warning: " << PF_WarnMsg[rc - START_PF_WARN] << "\n"; 57 | // Error codes are negative, so invert everything 58 | else if (-rc >= -START_PF_ERR && -rc < -PF_LASTERROR) 59 | // Print error 60 | cerr << "PF error: " << PF_ErrorMsg[-rc + START_PF_ERR] << "\n"; 61 | else if (rc == PF_UNIX) 62 | #ifdef PC 63 | cerr << "OS error\n"; 64 | #else 65 | cerr << strerror(errno) << "\n"; 66 | #endif 67 | else if (rc == 0) 68 | cerr << "PF_PrintError called with return code of 0\n"; 69 | else 70 | cerr << "PF error: " << rc << " is out of bounds\n"; 71 | } 72 | -------------------------------------------------------------------------------- /src/pf_hashtable.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_hashtable.cc 3 | // Description: PF_HashTable class implementation 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // 7 | 8 | #include "pf_internal.h" 9 | #include "pf_hashtable.h" 10 | 11 | // 12 | // PF_HashTable 13 | // 14 | // Desc: Constructor for PF_HashTable object, which allows search, insert, 15 | // and delete of hash table entries. 16 | // In: numBuckets - number of hash table buckets 17 | // 18 | PF_HashTable::PF_HashTable(int _numBuckets) 19 | { 20 | // Initialize numBuckets local variable from parameter 21 | this->numBuckets = _numBuckets; 22 | 23 | // Allocate memory for hash table 24 | hashTable = new PF_HashEntry* [numBuckets]; 25 | 26 | // Initialize all buckets to empty 27 | for (int i = 0; i < numBuckets; i++) 28 | hashTable[i] = NULL; 29 | } 30 | 31 | // 32 | // ~PF_HashTable 33 | // 34 | // Desc: Destructor 35 | // 36 | PF_HashTable::~PF_HashTable() 37 | { 38 | // Clear out all buckets 39 | for (int i = 0; i < numBuckets; i++) { 40 | 41 | // Delete all entries in the bucket 42 | PF_HashEntry *entry = hashTable[i]; 43 | while (entry != NULL) { 44 | PF_HashEntry *next = entry->next; 45 | delete entry; 46 | entry = next; 47 | } 48 | } 49 | 50 | // Finally delete the hash table 51 | delete[] hashTable; 52 | } 53 | 54 | // 55 | // Find 56 | // 57 | // Desc: Find a hash table entry. 58 | // In: fd - file descriptor 59 | // pageNum - page number 60 | // Out: slot - set to slot associated with fd and pageNum 61 | // Ret: PF return code 62 | // 63 | RC PF_HashTable::Find(int fd, PageNum pageNum, int &slot) 64 | { 65 | // Get which bucket it should be in 66 | int bucket = Hash(fd, pageNum); 67 | 68 | if (bucket<0) 69 | return (PF_HASHNOTFOUND); 70 | 71 | // Go through the linked list of this bucket 72 | for (PF_HashEntry *entry = hashTable[bucket]; 73 | entry != NULL; 74 | entry = entry->next) { 75 | if (entry->fd == fd && entry->pageNum == pageNum) { 76 | 77 | // Found it 78 | slot = entry->slot; 79 | return (0); 80 | } 81 | } 82 | 83 | // Didn't find it 84 | return (PF_HASHNOTFOUND); 85 | } 86 | 87 | // 88 | // Insert 89 | // 90 | // Desc: Insert a hash table entry 91 | // In: fd - file descriptor 92 | // pagenum - page number 93 | // slot - slot associated with fd and pageNum 94 | // Ret: PF return code 95 | // 96 | RC PF_HashTable::Insert(int fd, PageNum pageNum, int slot) 97 | { 98 | // Get which bucket it should be in 99 | int bucket = Hash(fd, pageNum); 100 | 101 | // Check entry doesn't already exist in the bucket 102 | PF_HashEntry *entry; 103 | for (entry = hashTable[bucket]; 104 | entry != NULL; 105 | entry = entry->next) { 106 | if (entry->fd == fd && entry->pageNum == pageNum) 107 | return (PF_HASHPAGEEXIST); 108 | } 109 | 110 | // Allocate memory for new hash entry 111 | if ((entry = new PF_HashEntry) == NULL) 112 | return (PF_NOMEM); 113 | 114 | // Insert entry at head of list for this bucket 115 | entry->fd = fd; 116 | entry->pageNum = pageNum; 117 | entry->slot = slot; 118 | entry->next = hashTable[bucket]; 119 | entry->prev = NULL; 120 | if (hashTable[bucket] != NULL) 121 | hashTable[bucket]->prev = entry; 122 | hashTable[bucket] = entry; 123 | 124 | // Return ok 125 | return (0); 126 | } 127 | 128 | // 129 | // Delete 130 | // 131 | // Desc: Delete a hash table entry 132 | // In: fd - file descriptor 133 | // pagenum - page number 134 | // Ret: PF return code 135 | // 136 | RC PF_HashTable::Delete(int fd, PageNum pageNum) 137 | { 138 | // Get which bucket it should be in 139 | int bucket = Hash(fd, pageNum); 140 | 141 | // Find the entry is in this bucket 142 | PF_HashEntry *entry; 143 | for (entry = hashTable[bucket]; 144 | entry != NULL; 145 | entry = entry->next) { 146 | if (entry->fd == fd && entry->pageNum == pageNum) 147 | break; 148 | } 149 | 150 | // Did we find hash entry? 151 | if (entry == NULL) 152 | return (PF_HASHNOTFOUND); 153 | 154 | // Remove this entry 155 | if (entry == hashTable[bucket]) 156 | hashTable[bucket] = entry->next; 157 | if (entry->prev != NULL) 158 | entry->prev->next = entry->next; 159 | if (entry->next != NULL) 160 | entry->next->prev = entry->prev; 161 | delete entry; 162 | 163 | // Return ook 164 | return (0); 165 | } 166 | 167 | 168 | -------------------------------------------------------------------------------- /src/pf_hashtable.h: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_hashtable.h 3 | // Description: PF_HashTable class interface 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // 7 | 8 | #ifndef PF_HASHTABLE_H 9 | #define PF_HASHTABLE_H 10 | 11 | #include "pf_internal.h" 12 | 13 | // 14 | // HashEntry - Hash table bucket entries 15 | // 16 | struct PF_HashEntry { 17 | PF_HashEntry *next; // next hash table element or NULL 18 | PF_HashEntry *prev; // prev hash table element or NULL 19 | int fd; // file descriptor 20 | PageNum pageNum; // page number 21 | int slot; // slot of this page in the buffer 22 | }; 23 | 24 | // 25 | // PF_HashTable - allow search, insertion, and deletion of hash table entries 26 | // 27 | class PF_HashTable { 28 | public: 29 | PF_HashTable (int numBuckets); // Constructor 30 | ~PF_HashTable(); // Destructor 31 | RC Find (int fd, PageNum pageNum, int &slot); 32 | // Set slot to the hash table 33 | // entry for fd and pageNum 34 | RC Insert (int fd, PageNum pageNum, int slot); 35 | // Insert a hash table entry 36 | RC Delete (int fd, PageNum pageNum); // Delete a hash table entry 37 | 38 | private: 39 | int Hash (int fd, PageNum pageNum) const 40 | { return ((fd + pageNum) % numBuckets); } // Hash function 41 | int numBuckets; // Number of hash table buckets 42 | PF_HashEntry **hashTable; // Hash table 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/pf_internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_internal.h 3 | // Description: Declarations internal to the paged file component 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Jason McHugh (mchughj@cs.stanford.edu) 7 | // 8 | 9 | #ifndef PF_INTERNAL_H 10 | #define PF_INTERNAL_H 11 | 12 | #include 13 | #include 14 | #include "pf.h" 15 | 16 | // 17 | // Constants and defines 18 | // 19 | const int PF_BUFFER_SIZE = 40; // Number of pages in the buffer 20 | const int PF_HASH_TBL_SIZE = 20; // Size of hash table 21 | 22 | #define CREATION_MASK 0600 // r/w privileges to owner only 23 | #define PF_PAGE_LIST_END -1 // end of list of free pages 24 | #define PF_PAGE_USED -2 // page is being used 25 | 26 | // L_SET is used to indicate the "whence" argument of the lseek call 27 | // defined in "/usr/include/unistd.h". A value of 0 indicates to 28 | // move to the absolute location specified. 29 | #ifndef L_SET 30 | #define L_SET 0 31 | #endif 32 | 33 | // 34 | // PF_PageHdr: Header structure for pages 35 | // 36 | struct PF_PageHdr { 37 | int nextFree; // nextFree can be any of these values: 38 | // - the number of the next free page 39 | // - PF_PAGE_LIST_END if this is last free page 40 | // - PF_PAGE_USED if the page is not free 41 | }; 42 | 43 | // Justify the file header to the length of one page 44 | const int PF_FILE_HDR_SIZE = PF_PAGE_SIZE + sizeof(PF_PageHdr); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/pf_pagehandle.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: pf_pagehandle.cc 3 | // Description: PF_PageHandle class implementation 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // 7 | 8 | #include "pf_internal.h" 9 | 10 | // 11 | // Defines 12 | // 13 | #define INVALID_PAGE (-1) 14 | 15 | // 16 | // PF_PageHandle 17 | // 18 | // Desc: Default constructor for a page handle object 19 | // A page handle object provides access to the contents of a page 20 | // and the page's page number. The page handle object is constructed 21 | // here but it must be passed to one of the PF_FileHandle methods to 22 | // have it refer to a pinned page before it can be used to access the 23 | // contents of a page. Remember to call PF_FileHandle::UnpinPage() 24 | // to unpin the page when you are finished accessing it. 25 | // 26 | PF_PageHandle::PF_PageHandle() 27 | { 28 | pageNum = INVALID_PAGE; 29 | pPageData = NULL; 30 | } 31 | 32 | // 33 | // ~PF_PageHandle 34 | // 35 | // Desc: Destroy the page handle object. 36 | // If the page handle object refers to a pinned page, the page will 37 | // NOT be unpinned. 38 | // 39 | PF_PageHandle::~PF_PageHandle() 40 | { 41 | // Don't need to do anything 42 | } 43 | 44 | // 45 | // PF_PageHandle 46 | // 47 | // Desc: Copy constructor 48 | // If the incoming page handle object refers to a pinned page, 49 | // the page will NOT be pinned again. 50 | // In: pageHandle - page handle object from which to construct this object 51 | // 52 | PF_PageHandle::PF_PageHandle(const PF_PageHandle &pageHandle) 53 | { 54 | // Just copy the local variables since there is no local memory 55 | // allocation involved 56 | this->pageNum = pageHandle.pageNum; 57 | this->pPageData = pageHandle.pPageData; 58 | } 59 | 60 | // 61 | // operator= 62 | // 63 | // Desc: overload = operator 64 | // If the page handle object on the rhs refers to a pinned page, 65 | // the page will NOT be pinned again. 66 | // In: pageHandle - page handle object to set this object equal to 67 | // Ret: reference to *this 68 | // 69 | PF_PageHandle& PF_PageHandle::operator= (const PF_PageHandle &pageHandle) 70 | { 71 | // Check for self-assignment 72 | if (this != &pageHandle) { 73 | 74 | // Just copy the pointers since there is no local memory 75 | // allocation involved 76 | this->pageNum = pageHandle.pageNum; 77 | this->pPageData = pageHandle.pPageData; 78 | } 79 | 80 | // Return a reference to this 81 | return (*this); 82 | } 83 | 84 | // 85 | // GetData 86 | // 87 | // Desc: Access the contents of a page. The page handle object must refer 88 | // to a pinned page. 89 | // Out: pData - Set pData to point to the page contents 90 | // Ret: PF return code 91 | // 92 | RC PF_PageHandle::GetData(char *&pData) const 93 | { 94 | // Page must refer to a pinned page 95 | if (pPageData == NULL) 96 | return (PF_PAGEUNPINNED); 97 | 98 | // Set pData to point to page contents (after PF header) 99 | pData = pPageData; 100 | 101 | // Return ok 102 | return (0); 103 | } 104 | 105 | // 106 | // GetPageNum 107 | // 108 | // Desc: Access the page number. The page handle object must refer to 109 | // a pinned page. 110 | // Out: pageNum - contains the page number 111 | // Ret: PF return code 112 | // 113 | RC PF_PageHandle::GetPageNum(PageNum &_pageNum) const 114 | { 115 | 116 | // Page must refer to a pinned page 117 | if (pPageData == NULL) 118 | return (PF_PAGEUNPINNED); 119 | 120 | // Set page number 121 | _pageNum = this->pageNum; 122 | 123 | // Return ok 124 | return (0); 125 | } 126 | -------------------------------------------------------------------------------- /src/pf_statistics.cc: -------------------------------------------------------------------------------- 1 | // 2 | // pf_statistics.cc 3 | // 4 | 5 | // This file contains the procedure to display all the statistics for the 6 | // PF layer. 7 | 8 | // Code written by Andre Bergholz, who was the TA for 2000 9 | 10 | // 11 | // This file only makes sense when the PF Statistics layer is defined 12 | // 13 | #ifdef PF_STATS 14 | 15 | #include 16 | #include "pf.h" 17 | #include "statistics.h" 18 | 19 | using namespace std; 20 | 21 | // This is defined within pf_buffermgr.cc 22 | extern StatisticsMgr *pStatisticsMgr; 23 | 24 | void PF_Statistics() 25 | { 26 | // First get all the statistics, must remember to delete memory returned 27 | int *piGP = pStatisticsMgr->Get(PF_GETPAGE); 28 | int *piPF = pStatisticsMgr->Get(PF_PAGEFOUND); 29 | int *piPNF = pStatisticsMgr->Get(PF_PAGENOTFOUND); 30 | int *piRP = pStatisticsMgr->Get(PF_READPAGE); 31 | int *piWP = pStatisticsMgr->Get(PF_WRITEPAGE); 32 | int *piFP = pStatisticsMgr->Get(PF_FLUSHPAGES); 33 | 34 | cout << "PF Layer Statistics\n"; 35 | cout << "-------------------\n"; 36 | 37 | cout << "Total number of calls to GetPage Routine: "; 38 | if (piGP) cout << *piGP; else cout << "None"; 39 | cout << "\n Number found: "; 40 | if (piPF) cout << *piPF; else cout << "None"; 41 | cout << "\n Number not found: "; 42 | if (piPNF) cout << *piPNF; else cout << "None"; 43 | cout << "\n-------------------\n"; 44 | 45 | cout << "Number of read requests: "; 46 | if (piRP) cout << *piRP; else cout << "None"; 47 | cout << "\nNumber of write requests: "; 48 | if (piWP) cout << *piWP; else cout << "None"; 49 | cout << "\n-------------------\n"; 50 | cout << "Number of flushes: "; 51 | if (piFP) cout << *piFP; else cout << "None"; 52 | cout << "\n-------------------\n"; 53 | 54 | // Must delete the memory returned from StatisticsMgr::Get 55 | delete piGP; 56 | delete piPF; 57 | delete piPNF; 58 | delete piRP; 59 | delete piWP; 60 | delete piFP; 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/printer.h: -------------------------------------------------------------------------------- 1 | // 2 | // printer.h 3 | // 4 | 5 | // This file contains the interface for the Printer class and some 6 | // functions that will be used by both the SM and QL components. 7 | 8 | #ifndef _HELPER 9 | #define _HELPER 10 | 11 | #include 12 | #include 13 | #include "redbase.h" // For definition of MAXNAME 14 | 15 | #define MAXPRINTSTRING ((2*MAXNAME) + 5) 16 | 17 | // 18 | // DataAttrInfo 19 | // 20 | // This struct stores the information that is kept within in 21 | // attribute catalog. It identifies a relation name, attribute name 22 | // and the location type and length of the attribute. 23 | // 24 | struct DataAttrInfo 25 | { 26 | // Default constructor 27 | DataAttrInfo() { 28 | memset(relName, 0, MAXNAME + 1); 29 | memset(attrName, 0, MAXNAME + 1); 30 | }; 31 | 32 | // Copy constructor 33 | DataAttrInfo( const DataAttrInfo &d ) { 34 | strcpy (relName, d.relName); 35 | strcpy (attrName, d.attrName); 36 | offset = d.offset; 37 | attrType = d.attrType; 38 | attrLength = d.attrLength; 39 | indexNo = d.indexNo; 40 | }; 41 | 42 | DataAttrInfo& operator=(const DataAttrInfo &d) { 43 | if (this != &d) { 44 | strcpy (relName, d.relName); 45 | strcpy (attrName, d.attrName); 46 | offset = d.offset; 47 | attrType = d.attrType; 48 | attrLength = d.attrLength; 49 | indexNo = d.indexNo; 50 | } 51 | return (*this); 52 | }; 53 | 54 | char relName[MAXNAME+1]; // Relation name 55 | char attrName[MAXNAME+1]; // Attribute name 56 | int offset; // Offset of attribute 57 | AttrType attrType; // Type of attribute 58 | int attrLength; // Length of attribute 59 | int indexNo; // Index number of attribute 60 | }; 61 | 62 | // Print some number of spaces 63 | void Spaces(int maxLength, int printedSoFar); 64 | 65 | class Printer { 66 | public: 67 | // Constructor. Takes as arguments an array of attributes along with 68 | // the length of the array. 69 | Printer(const DataAttrInfo *attributes, const int attrCount); 70 | ~Printer(); 71 | 72 | void PrintHeader(std::ostream &c) const; 73 | 74 | // Two flavors for the Print routine. The first takes a char* to the 75 | // data and is useful when the data corresponds to a single record in 76 | // a table -- since in this situation you can just send in the 77 | // RecData. The second will be useful in the QL layer. 78 | void Print(std::ostream &c, const char * const data); 79 | void Print(std::ostream &c, const void * const data[]); 80 | 81 | void PrintFooter(std::ostream &c) const; 82 | 83 | private: 84 | DataAttrInfo *attributes; 85 | int attrCount; 86 | 87 | // An array of strings for the header information 88 | char **psHeader; 89 | // Number of spaces between each attribute 90 | int *spaces; 91 | 92 | // The number of tuples printed 93 | int iCount; 94 | }; 95 | 96 | 97 | #ifndef min 98 | #define min(a,b) (((a) < (b)) ? (a) : (b)) 99 | #endif 100 | 101 | #ifndef max 102 | #define max(a,b) (((a) > (b)) ? (a) : (b)) 103 | #endif 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/ql.h: -------------------------------------------------------------------------------- 1 | // 2 | // ql.h 3 | // Query Language Component Interface 4 | // 5 | 6 | // This file only gives the stub for the QL component 7 | 8 | #ifndef QL_H 9 | #define QL_H 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "redbase.h" 18 | #include "parser.h" 19 | #include "rm.h" 20 | #include "ix.h" 21 | #include "sm.h" 22 | #include "ql_node.h" 23 | 24 | 25 | typedef struct QO_Rel{ 26 | int relIdx; 27 | int indexAttr; 28 | int indexCond; 29 | } QO_Rel; 30 | 31 | // 32 | // QL_Manager: query language (DML) 33 | // 34 | class QL_Manager { 35 | friend class QL_Node; 36 | friend class Node_Rel; 37 | friend class QL_NodeJoin; 38 | friend class QL_NodeRel; 39 | friend class QL_NodeSel; 40 | friend class QL_NodeProj; 41 | friend class QO_Manager; 42 | public: 43 | QL_Manager (SM_Manager &smm, IX_Manager &ixm, RM_Manager &rmm); 44 | ~QL_Manager(); // Destructor 45 | 46 | RC Select (int nSelAttrs, // # attrs in select clause 47 | const RelAttr selAttrs[], // attrs in select clause 48 | int nRelations, // # relations in from clause 49 | const char * const relations[], // relations in from clause 50 | int nConditions, // # conditions in where clause 51 | const Condition conditions[]); // conditions in where clause 52 | 53 | RC Insert (const char *relName, // relation to insert into 54 | int nValues, // # values 55 | const Value values[]); // values to insert 56 | 57 | RC Delete (const char *relName, // relation to delete from 58 | int nConditions, // # conditions in where clause 59 | const Condition conditions[]); // conditions in where clause 60 | 61 | RC Update (const char *relName, // relation to update 62 | const RelAttr &updAttr, // attribute to update 63 | const int bIsValue, // 1 if RHS is a value, 0 if attribute 64 | const RelAttr &rhsRelAttr, // attr on RHS to set LHS equal to 65 | const Value &rhsValue, // or value to set attr equal to 66 | int nConditions, // # conditions in where clause 67 | const Condition conditions[]); // conditions in where clause 68 | 69 | private: 70 | // Resets the class variables for the next query command 71 | RC Reset(); 72 | // Checks whether an attribute is valid for a query command 73 | bool IsValidAttr(const RelAttr attr); 74 | // Parses the relations, making sure they're in the database, and there aren't duplicates 75 | RC ParseRelNoDup(int nRelations, const char * const relations[]); 76 | 77 | // Parses the select attributes, making sure they're valid 78 | RC ParseSelectAttrs(int nSelAttrs, const RelAttr selAttrs[]); 79 | // Gets the attribute attrCatEntry associated with a specific attribute 80 | RC GetAttrCatEntry(const RelAttr attr, AttrCatEntry *&entry); 81 | // Get the attribute attrEntries position associated with a specific attribute 82 | RC GetAttrCatEntryPos(const RelAttr attr, int &index); 83 | // Parses the conditions to make sure that they're valid 84 | RC ParseConditions(int nConditions, const Condition conditions[]); 85 | 86 | // Set up the global relation and attribute lists (attrEntries and relEntries) 87 | // for one relation (used in Delete and Update) 88 | RC SetUpOneRelation(const char *relName); 89 | // Check that the update attributes are valid 90 | RC CheckUpdateAttrs(const RelAttr &updAttr, 91 | const int bIsValue, 92 | const RelAttr &rhsRelAttr, 93 | const Value &rhsValue); 94 | // Run delete given the top node 95 | RC RunDelete(QL_Node *topNode); 96 | // Run update given the top node 97 | RC RunUpdate(QL_Node *topNode, const RelAttr &updAttr, 98 | const int bIsValue, 99 | const RelAttr &rhsRelAttr, 100 | const Value &rhsValue); 101 | // Runs select given the top node 102 | RC RunSelect(QL_Node *topNode); 103 | // Inserts a set of values into a relation 104 | RC InsertIntoRelation(const char *relName, int tupleLength, int nValues, const Value values[]); 105 | // Inserts a new record in all the indices belonging to that relation 106 | RC InsertIntoIndex(char *recbuf, RID recRID); 107 | // Creates a record from the values entered via the query command 108 | RC CreateRecord(char *recbuf, AttrCatEntry *aEntries, int nValues, const Value values[]); 109 | 110 | 111 | // Used for update for keeping track of attributes that have indices. 112 | RC CleanUpRun(Attr* attributes, RM_FileHandle &relFH); 113 | RC SetUpRun(Attr* attributes, RM_FileHandle &relFH); 114 | 115 | // Cleans up the nodes after a run 116 | RC CleanUpNodes(QL_Node *topNode); 117 | // Count the number of conditions associated with a relation 118 | RC CountNumConditions(int relIndex, int &numConds); 119 | // Set up the first node in creating the query tree 120 | RC SetUpFirstNode(QL_Node *&topNode); 121 | // Sets up the entire query tree and returns the top node in topNode 122 | RC SetUpNodes(QL_Node *&topNode, int nSelAttrs, const RelAttr selAttrs[]); 123 | // Sets up the entire query tree based on the return of the Query optimizer and returns the 124 | // top node in topNode 125 | RC SetUpNodesWithQO(QL_Node *&topNode, QO_Rel* qorels, int nSelAttrs, const RelAttr selAttrs[]); 126 | RC SetUpFirstNodeWithQO(QL_Node *&topNode, QO_Rel* qorels); 127 | RC JoinRelationWithQO(QL_Node *&topNode, QO_Rel* qorels, QL_Node *currNode, int relIndex); 128 | RC RecalcCondToRel(QO_Rel* qorels); 129 | RC AttrToRelIndex(const RelAttr attr, int& relIndex); 130 | // Creates a join node and a relation node for the relation specified, and 131 | // returns the top node in topNode 132 | RC JoinRelation(QL_Node *&topNode, QL_Node *currNode, int relIndex); 133 | 134 | // Set up the printing parameters 135 | RC SetUpPrinter(QL_Node *topNode, DataAttrInfo *attributes); 136 | RC SetUpPrinterInsert(DataAttrInfo *attributes); 137 | 138 | 139 | 140 | RM_Manager &rmm; 141 | IX_Manager &ixm; 142 | SM_Manager &smm; 143 | 144 | // helpers for query parsing 145 | // maps from relation name to its index number in relEntries 146 | std::map relToInt; 147 | // maps from attribute name to a set of its relation names 148 | std::map > attrToRel; 149 | // maps from relation name to the index of its first relation 150 | std::map relToAttrIndex; 151 | // maps from condition to the relation it's meant to be grouped with 152 | std::map conditionToRel; 153 | 154 | // Holds the relation relCat entries 155 | RelCatEntry *relEntries; 156 | // Holds the attribute attrCat entries. The attributes are ordered in the 157 | // appropriate order following the relation, in the order of the relations 158 | AttrCatEntry *attrEntries; 159 | 160 | // number of attributes, relations and conditions 161 | int nAttrs; 162 | int nRels; 163 | int nConds; 164 | // whether it's an update or not (whether to use indices or not) 165 | bool isUpdate; 166 | 167 | // pointer to the condition list 168 | const Condition *condptr; 169 | 170 | 171 | }; 172 | 173 | // 174 | // Print-error function 175 | // 176 | void QL_PrintError(RC rc); 177 | 178 | #define QL_BADINSERT (START_QL_WARN + 0) // Bad insert 179 | #define QL_DUPRELATION (START_QL_WARN + 1) // Duplicate relation 180 | #define QL_BADSELECTATTR (START_QL_WARN + 2) // Bad select attribute 181 | #define QL_ATTRNOTFOUND (START_QL_WARN + 3) // Attribute not found 182 | #define QL_BADCOND (START_QL_WARN + 4) // Bad condition 183 | #define QL_BADCALL (START_QL_WARN + 5) // Bad/invalid call 184 | #define QL_CONDNOTMET (START_QL_WARN + 6) // Condition has not been met 185 | #define QL_BADUPDATE (START_QL_WARN + 7) // Bad update statement 186 | #define QL_EOI (START_QL_WARN + 8) // End of iterator 187 | #define QO_BADCONDITION (START_QL_WARN + 9) 188 | #define QO_INVALIDBIT (START_QL_WARN + 10) 189 | #define QL_LASTWARN QL_EOI 190 | 191 | #define QL_INVALIDDB (START_QL_ERR - 0) 192 | #define QL_ERROR (START_QL_ERR - 1) // error 193 | #define QL_LASTERROR QL_ERROR 194 | 195 | 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/ql_error.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: ql_error.cc 3 | // Description: QL_PrintError functions 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Yifei Huang (yifei@stanford.edu) 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "ql.h" 13 | 14 | using namespace std; 15 | 16 | // 17 | // Error table 18 | // 19 | static char *QL_WarnMsg[] = { 20 | (char*)"bad insert", 21 | (char*)"duplicate relation", 22 | (char*)"bad attribute", 23 | (char*)"attribute not found", 24 | (char*)"bad select condition", 25 | (char*)"bad call", 26 | (char*)"condition not met", 27 | (char*)"bad update value", 28 | (char*)"end of iterator" 29 | }; 30 | 31 | static char *QL_ErrorMsg[] = { 32 | (char*)"Invalid database", 33 | (char*)"QL Error" 34 | }; 35 | 36 | // 37 | // RM_PrintError 38 | // 39 | // Desc: Send a message corresponding to a RM return code to cerr 40 | // Assumes PF_UNIX is last valid RM return code 41 | // In: rc - return code for which a message is desired 42 | // 43 | void QL_PrintError(RC rc) 44 | { 45 | // Check the return code is within proper limits 46 | if (rc >= START_QL_WARN && rc <= QL_LASTWARN) 47 | // Print warning 48 | cerr << "QL warning: " << QL_WarnMsg[rc - START_QL_WARN] << "\n"; 49 | // Error codes are negative, so invert everything 50 | else if (-rc >= -START_QL_ERR && -rc < -QL_LASTERROR) 51 | // Print error 52 | cerr << "QL error: " << QL_ErrorMsg[-rc + START_QL_ERR] << "\n"; 53 | else if (rc == PF_UNIX) 54 | #ifdef PC 55 | cerr << "OS error\n"; 56 | #else 57 | cerr << strerror(errno) << "\n"; 58 | #endif 59 | else if (rc == 0) 60 | cerr << "QL_PrintError called with return code of 0\n"; 61 | else 62 | cerr << "QL error: " << rc << " is out of bounds\n"; 63 | } 64 | -------------------------------------------------------------------------------- /src/ql_manager_stub.cc: -------------------------------------------------------------------------------- 1 | // 2 | // ql_manager_stub.cc 3 | // 4 | 5 | // Note that for the SM component (HW3) the QL is actually a 6 | // simple stub that will allow everything to compile. Without 7 | // a QL stub, we would need two parsers. 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "redbase.h" 16 | #include "ql.h" 17 | #include "sm.h" 18 | #include "ix.h" 19 | #include "rm.h" 20 | 21 | using namespace std; 22 | 23 | // 24 | // QL_Manager::QL_Manager(SM_Manager &smm, IX_Manager &ixm, RM_Manager &rmm) 25 | // 26 | // Constructor for the QL Manager 27 | // 28 | QL_Manager::QL_Manager(SM_Manager &smm, IX_Manager &ixm, RM_Manager &rmm) 29 | { 30 | // Can't stand unused variable warnings! 31 | assert (&smm && &ixm && &rmm); 32 | } 33 | 34 | // 35 | // QL_Manager::~QL_Manager() 36 | // 37 | // Destructor for the QL Manager 38 | // 39 | QL_Manager::~QL_Manager() 40 | { 41 | } 42 | 43 | // 44 | // Handle the select clause 45 | // 46 | RC QL_Manager::Select(int nSelAttrs, const RelAttr selAttrs[], 47 | int nRelations, const char * const relations[], 48 | int nConditions, const Condition conditions[]) 49 | { 50 | int i; 51 | 52 | cout << "Select\n"; 53 | 54 | cout << " nSelAttrs = " << nSelAttrs << "\n"; 55 | for (i = 0; i < nSelAttrs; i++) 56 | cout << " selAttrs[" << i << "]:" << selAttrs[i] << "\n"; 57 | 58 | cout << " nRelations = " << nRelations << "\n"; 59 | for (i = 0; i < nRelations; i++) 60 | cout << " relations[" << i << "] " << relations[i] << "\n"; 61 | 62 | cout << " nCondtions = " << nConditions << "\n"; 63 | for (i = 0; i < nConditions; i++) 64 | cout << " conditions[" << i << "]:" << conditions[i] << "\n"; 65 | 66 | return 0; 67 | } 68 | 69 | // 70 | // Insert the values into relName 71 | // 72 | RC QL_Manager::Insert(const char *relName, 73 | int nValues, const Value values[]) 74 | { 75 | int i; 76 | 77 | cout << "Insert\n"; 78 | 79 | cout << " relName = " << relName << "\n"; 80 | cout << " nValues = " << nValues << "\n"; 81 | for (i = 0; i < nValues; i++) 82 | cout << " values[" << i << "]:" << values[i] << "\n"; 83 | 84 | return 0; 85 | } 86 | 87 | // 88 | // Delete from the relName all tuples that satisfy conditions 89 | // 90 | RC QL_Manager::Delete(const char *relName, 91 | int nConditions, const Condition conditions[]) 92 | { 93 | int i; 94 | 95 | cout << "Delete\n"; 96 | 97 | cout << " relName = " << relName << "\n"; 98 | cout << " nCondtions = " << nConditions << "\n"; 99 | for (i = 0; i < nConditions; i++) 100 | cout << " conditions[" << i << "]:" << conditions[i] << "\n"; 101 | 102 | return 0; 103 | } 104 | 105 | 106 | // 107 | // Update from the relName all tuples that satisfy conditions 108 | // 109 | RC QL_Manager::Update(const char *relName, 110 | const RelAttr &updAttr, 111 | const int bIsValue, 112 | const RelAttr &rhsRelAttr, 113 | const Value &rhsValue, 114 | int nConditions, const Condition conditions[]) 115 | { 116 | int i; 117 | 118 | cout << "Update\n"; 119 | 120 | cout << " relName = " << relName << "\n"; 121 | cout << " updAttr:" << updAttr << "\n"; 122 | if (bIsValue) 123 | cout << " rhs is value: " << rhsValue << "\n"; 124 | else 125 | cout << " rhs is attribute: " << rhsRelAttr << "\n"; 126 | 127 | cout << " nCondtions = " << nConditions << "\n"; 128 | for (i = 0; i < nConditions; i++) 129 | cout << " conditions[" << i << "]:" << conditions[i] << "\n"; 130 | 131 | return 0; 132 | } 133 | 134 | // 135 | // void QL_PrintError(RC rc) 136 | // 137 | // This function will accept an Error code and output the appropriate 138 | // error. 139 | // 140 | void QL_PrintError(RC rc) 141 | { 142 | cout << "QL_PrintError\n rc=" << rc << "\n"; 143 | } 144 | -------------------------------------------------------------------------------- /src/ql_node.h: -------------------------------------------------------------------------------- 1 | // 2 | // ql_node.h 3 | // 4 | // The QL Node interface 5 | // 6 | #ifndef QL_NODE_H 7 | #define QL_NODE_H 8 | 9 | 10 | /* 11 | * This holds information about a condition to meet 12 | */ 13 | typedef struct Cond{ 14 | int offset1; // offset of LHS attribute 15 | // comparator - depends on which operator is used in this condition 16 | bool (*comparator) (void * , void *, AttrType, int); 17 | bool isValue; // whether this is a value or not 18 | void* data; // the pointer to the data 19 | int offset2; // the offset of RHS attribute 20 | int length; // length of LHS attribute 21 | int length2; // length of RHS value/attribute 22 | AttrType type; // attribute type 23 | } Cond; 24 | 25 | /* 26 | * The abstract class for nodes 27 | */ 28 | class QL_Node { 29 | friend class QL_Manager; 30 | friend class QL_NodeJoin; 31 | public: 32 | QL_Node(QL_Manager &qlm); 33 | ~QL_Node(); 34 | 35 | virtual RC OpenIt() = 0; 36 | virtual RC GetNext(char * data) = 0; 37 | virtual RC GetNextRec(RM_Record &rec) = 0; 38 | virtual RC CloseIt() = 0; 39 | virtual RC DeleteNodes() = 0; 40 | virtual RC PrintNode(int numTabs) = 0; 41 | virtual bool IsRelNode() = 0; 42 | virtual RC OpenIt(void *data) = 0; 43 | virtual RC UseIndex(int attrNum, int indexNumber, void *data) = 0; 44 | // Prints a condition 45 | RC PrintCondition(const Condition condition); 46 | // Given a index of an attribute, returns its offset and length 47 | RC IndexToOffset(int index, int &offset, int &length); 48 | // Add a condition to the node 49 | RC AddCondition(const Condition conditions, int condNum); 50 | // Check to see if the conditions to this node are met 51 | RC CheckConditions(char *recData); 52 | // Get the attribute list for this node, and the list size 53 | RC GetAttrList(int *&attrList, int &attrListSize); 54 | // Get the tuple lenght of this node 55 | RC GetTupleLength(int &tupleLength); 56 | protected: 57 | QL_Manager &qlm; // Reference to QL manager 58 | bool isOpen; // Whether the node is open or not 59 | int tupleLength; // the length of a tuple in this node 60 | int *attrsInRec; // list of indices of the attribute in this node 61 | int attrsInRecSize; // size of the attribute list 62 | bool listsInitialized; // indicator for whether memory has been initialized 63 | 64 | // The condition list 65 | Cond *condList; 66 | int condIndex; // the # of conditions currently in this node 67 | int* condsInNode; // maps the condition from the index in this list, to the 68 | // index in the list in QL 69 | bool useIndexJoin; 70 | }; 71 | 72 | /* Project nodes 73 | */ 74 | class QL_NodeProj: public QL_Node { 75 | friend class QL_Manager; 76 | public: 77 | QL_NodeProj(QL_Manager &qlm, QL_Node &prevNode); 78 | ~QL_NodeProj(); 79 | 80 | RC OpenIt(); 81 | RC GetNext(char *data); 82 | RC CloseIt(); 83 | RC GetNextRec(RM_Record &rec); 84 | RC DeleteNodes(); 85 | RC PrintNode(int numTabs); 86 | bool IsRelNode(); 87 | RC OpenIt(void *data); 88 | RC UseIndex(int attrNum, int indexNumber, void *data); 89 | 90 | // Add a projection by specifying the index of the attribute to keep 91 | RC AddProj(int attrIndex); 92 | RC ReconstructRec(char *data); // reconstruct the record, and put it in data 93 | RC SetUpNode(int numAttrToKeep); 94 | private: 95 | QL_Node &prevNode; // previous node 96 | 97 | int numAttrsToKeep; // # of attributes to keep 98 | 99 | char *buffer; 100 | }; 101 | 102 | 103 | /* Select nodes 104 | */ 105 | class QL_NodeSel: public QL_Node { 106 | friend class QL_Manager; 107 | public: 108 | QL_NodeSel(QL_Manager &qlm, QL_Node &prevNode); 109 | ~QL_NodeSel(); 110 | 111 | RC OpenIt(); 112 | RC GetNext(char *data); 113 | RC CloseIt(); 114 | RC GetNextRec(RM_Record &rec); 115 | RC DeleteNodes(); 116 | RC PrintNode(int numTabs); 117 | bool IsRelNode(); 118 | RC OpenIt(void *data); 119 | RC UseIndex(int attrNum, int indexNumber, void *data); 120 | 121 | RC AddCondition(const Condition conditions, int condNum); 122 | RC SetUpNode(int numConds); 123 | private: 124 | QL_Node& prevNode; 125 | 126 | char *buffer; 127 | }; 128 | 129 | /* Join nodes 130 | */ 131 | class QL_NodeJoin: public QL_Node { 132 | friend class QL_Manager; 133 | public: 134 | QL_NodeJoin(QL_Manager &qlm, QL_Node &node1, QL_Node &node2); 135 | ~QL_NodeJoin(); 136 | 137 | RC OpenIt(); 138 | RC GetNext(char *data); 139 | RC CloseIt(); 140 | RC GetNextRec(RM_Record &rec); 141 | RC DeleteNodes(); 142 | RC PrintNode(int numTabs); 143 | bool IsRelNode(); 144 | RC OpenIt(void *data); 145 | RC UseIndex(int attrNum, int indexNumber, void *data); 146 | 147 | RC UseIndexJoin(int indexAttr, int subNodeAttr, int indexNumber); 148 | RC AddCondition(const Condition conditions, int condNum); 149 | RC SetUpNode(int numConds); 150 | private: 151 | QL_Node &node1; 152 | QL_Node &node2; 153 | int firstNodeSize; 154 | char * buffer; 155 | 156 | bool gotFirstTuple; 157 | 158 | bool useIndexJoin; 159 | int indexAttr; 160 | }; 161 | 162 | /* Relation nodes 163 | */ 164 | class QL_NodeRel: public QL_Node { 165 | friend class QL_Manager; 166 | friend class QL_NodeJoin; 167 | public: 168 | QL_NodeRel(QL_Manager &qlm, RelCatEntry *rEntry); 169 | ~QL_NodeRel(); 170 | 171 | RC OpenIt(); 172 | RC GetNext(char *data); 173 | RC CloseIt(); 174 | RC GetNextRec(RM_Record &rec); 175 | RC DeleteNodes(); 176 | RC PrintNode(int numTabs); 177 | bool IsRelNode(); 178 | 179 | 180 | RC SetUpNode(int *attrs, int attrlistSize); 181 | RC UseIndex(int attrNum, int indexNumber, void *data); 182 | RC OpenIt(void *data); 183 | private: 184 | RC RetrieveNextRec(RM_Record &rec, char *&recData); 185 | // relation name, and indicator for whether it's been malloced 186 | char *relName; 187 | bool relNameInitialized; 188 | 189 | bool useIndex; // whether to use the index 190 | int indexNo; // index number to use 191 | void *value; // equality value for index 192 | int indexAttr; // index of attribute for the index 193 | 194 | RM_FileHandle fh; // filehandle/scans for retrieving records from relation 195 | IX_IndexHandle ih; 196 | RM_FileScan fs; 197 | IX_IndexScan is; 198 | 199 | }; 200 | 201 | 202 | 203 | 204 | 205 | #endif -------------------------------------------------------------------------------- /src/ql_nodejoin.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: ql_nodejoin.cc 3 | // Description: Abstract class for query processing nodes 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | 18 | 19 | using namespace std; 20 | 21 | /* 22 | * Create the node by constructing with the two nodes referring to 23 | * nodes to join. 24 | */ 25 | QL_NodeJoin::QL_NodeJoin(QL_Manager &qlm, QL_Node &node1, QL_Node &node2) : 26 | QL_Node(qlm), node1(node1), node2(node2){ 27 | isOpen = false; 28 | listsInitialized = false; 29 | attrsInRecSize = 0; 30 | tupleLength = 0; 31 | condIndex = 0; 32 | firstNodeSize = 0; 33 | gotFirstTuple = false; 34 | useIndexJoin = false; 35 | } 36 | 37 | /* 38 | * delete all memory 39 | */ 40 | QL_NodeJoin::~QL_NodeJoin(){ 41 | if(listsInitialized = true){ 42 | free(attrsInRec); 43 | free(condList); 44 | free(buffer); 45 | free(condsInNode); 46 | } 47 | } 48 | 49 | /* 50 | * Set up the node with a max number of conditions that the 51 | * join must meet 52 | */ 53 | RC QL_NodeJoin::SetUpNode(int numConds){ 54 | RC rc = 0; 55 | // First sets up the attribute list for this node 56 | // by retrieving the attribute lists for both the previous nodes 57 | int *attrList1; 58 | int *attrList2; 59 | int attrListSize1; 60 | int attrListSize2; 61 | if((rc = node1.GetAttrList(attrList1, attrListSize1)) || 62 | (rc = node2.GetAttrList(attrList2, attrListSize2))) 63 | return (rc); 64 | attrsInRecSize = attrListSize1 + attrListSize2; 65 | 66 | attrsInRec = (int*)malloc(attrsInRecSize*sizeof(int)); 67 | memset((void *)attrsInRec, 0, sizeof(attrsInRec)); 68 | for(int i = 0; i < attrListSize1; i++){ 69 | attrsInRec[i] = attrList1[i]; 70 | } 71 | for(int i=0; i < attrListSize2; i++){ 72 | attrsInRec[attrListSize1+i] = attrList2[i]; 73 | } 74 | 75 | // Malloc the list of conditions to be met 76 | condList = (Cond *)malloc(numConds * sizeof(Cond)); 77 | for(int i= 0; i < numConds; i++){ 78 | condList[i] = {0, NULL, true, NULL, 0, 0, INT}; 79 | } 80 | condsInNode = (int*)malloc(numConds * sizeof(int)); 81 | 82 | int tupleLength1, tupleLength2; 83 | node1.GetTupleLength(tupleLength1); 84 | node2.GetTupleLength(tupleLength2); 85 | tupleLength = tupleLength1 + tupleLength2; 86 | firstNodeSize = tupleLength1; 87 | 88 | // Create the buffer to hold the tuples from the previous nodes 89 | buffer = (char *)malloc(tupleLength); 90 | memset((void*)buffer, 0, sizeof(buffer)); 91 | listsInitialized = true; 92 | return (0); 93 | } 94 | 95 | 96 | /* 97 | * Open the iterator by opening previous nodes 98 | */ 99 | RC QL_NodeJoin::OpenIt(){ 100 | RC rc = 0; 101 | if(!useIndexJoin){ 102 | if((rc = node1.OpenIt()) || (rc = node2.OpenIt())) 103 | return (rc); 104 | } 105 | else{ 106 | if((rc = node1.OpenIt() )) 107 | return (rc); 108 | } 109 | gotFirstTuple = false; 110 | 111 | return (0); 112 | } 113 | 114 | /* 115 | * Returns the next tuple join that satisfies the conditions 116 | */ 117 | RC QL_NodeJoin::GetNext(char *data){ 118 | RC rc = 0; 119 | // Retrieve the first tuple, marking the start of the iterator 120 | if(gotFirstTuple == false && ! useIndexJoin){ 121 | if((rc = node1.GetNext(buffer))) 122 | return (rc); 123 | } 124 | else if(gotFirstTuple == false && useIndexJoin){ 125 | if((rc = node1.GetNext(buffer))) 126 | return (rc); 127 | int offset, length; 128 | IndexToOffset(indexAttr, offset, length); 129 | if((rc = node2.OpenIt(buffer + offset))) 130 | return (rc); 131 | } 132 | gotFirstTuple = true; 133 | while(true && !useIndexJoin){ 134 | if((rc = node2.GetNext(buffer + firstNodeSize)) && rc == QL_EOI){ 135 | // no more in buffer2, restart it, and get the next node in buf1 136 | if((rc = node1.GetNext(buffer))) 137 | return (rc); 138 | if((rc = node2.CloseIt()) || (rc = node2.OpenIt())) 139 | return (rc); 140 | if((rc = node2.GetNext(buffer + firstNodeSize))) 141 | return (rc); 142 | } 143 | // keep retrieving until condition is met 144 | RC comp = CheckConditions(buffer); 145 | if(comp == 0) 146 | break; 147 | } 148 | while(true && useIndexJoin){ 149 | if((rc = node2.GetNext(buffer + firstNodeSize)) ){ 150 | // no more in buffer 2, restart it and get the next node in buf1 151 | int found = false; 152 | while(found == false){ 153 | if((rc = node1.GetNext(buffer))) 154 | return (rc); 155 | int offset, length; 156 | IndexToOffset(indexAttr, offset, length); 157 | if((rc = node2.CloseIt()) || (rc = node2.OpenIt(buffer + offset))) 158 | return (rc); 159 | if((rc = node2.GetNext(buffer + firstNodeSize)) && rc == QL_EOI){ 160 | //return (rc); 161 | found = false; 162 | } 163 | else 164 | found = true; 165 | 166 | } 167 | } 168 | RC comp = CheckConditions(buffer); 169 | if (comp == 0) 170 | break; 171 | } 172 | memcpy(data, buffer, tupleLength); 173 | return (0); 174 | } 175 | 176 | /* 177 | * Don't allow join nodes to retrieve records 178 | */ 179 | RC QL_NodeJoin::GetNextRec(RM_Record &rec){ 180 | return (QL_BADCALL); 181 | } 182 | 183 | /* 184 | * Close the iterator by closing previous nodes 185 | */ 186 | RC QL_NodeJoin::CloseIt(){ 187 | RC rc = 0; 188 | if((rc = node1.CloseIt()) || (rc = node2.CloseIt())) 189 | return (rc); 190 | gotFirstTuple = false; 191 | return (0); 192 | } 193 | 194 | /* 195 | * Print the node, and instruct it to print its previous nodes 196 | */ 197 | RC QL_NodeJoin::PrintNode(int numTabs){ 198 | for(int i=0; i < numTabs; i++){ 199 | cout << "\t"; 200 | } 201 | cout << "--JOIN: \n"; 202 | for(int i = 0; i < condIndex; i++){ 203 | for(int j=0; j indexAttr = indexAttr; 235 | node2.UseIndex(subNodeAttr, indexNumber, NULL); 236 | node2.useIndexJoin= true; 237 | return (0); 238 | } 239 | 240 | bool QL_NodeJoin::IsRelNode(){ 241 | return false; 242 | } 243 | 244 | RC QL_NodeJoin::OpenIt(void *data){ 245 | return (QL_BADCALL); 246 | } 247 | 248 | RC QL_NodeJoin::UseIndex(int attrNum, int indexNumber, void *data){ 249 | return (QL_BADCALL); 250 | } 251 | 252 | -------------------------------------------------------------------------------- /src/ql_nodeproj.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: ql_nodeproj.cc 3 | // Description: Abstract class for query processing nodes 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | 18 | 19 | using namespace std; 20 | 21 | /* 22 | * Create the project node with a reference to the previous node 23 | */ 24 | QL_NodeProj::QL_NodeProj(QL_Manager &qlm, QL_Node &prevNode) : QL_Node(qlm), prevNode(prevNode) { 25 | isOpen = false; 26 | listsInitialized = false; 27 | attrsInRecSize = 0; 28 | tupleLength = 0; 29 | } 30 | 31 | /* 32 | * Free memory allocated to this node 33 | */ 34 | QL_NodeProj::~QL_NodeProj(){ 35 | if(listsInitialized == true){ 36 | free(attrsInRec); 37 | free(buffer); 38 | } 39 | listsInitialized = false; 40 | } 41 | 42 | /* 43 | * Set up the node by giving it the number of attributes to keep. 44 | * It allocates the memory to keep the list of indices referring to 45 | * attributes to keep 46 | */ 47 | RC QL_NodeProj::SetUpNode(int numAttrToKeep){ 48 | RC rc = 0; 49 | // malloc the list of attributes to keep 50 | attrsInRec = (int *)malloc(numAttrToKeep * sizeof(int)); 51 | memset((void*)attrsInRec, 0, sizeof(attrsInRec)); 52 | int attrsInRecSize = 0; 53 | 54 | // malloc the buffer to keep the data for a tuple passed 55 | // up from the previous node 56 | int bufLength; 57 | prevNode.GetTupleLength(bufLength); 58 | buffer = (char *)malloc(bufLength); 59 | memset((void*) buffer, 0, sizeof(buffer)); 60 | listsInitialized = true; 61 | 62 | return (0); 63 | } 64 | 65 | /* 66 | * Open the iterator by opening the previous node 67 | */ 68 | RC QL_NodeProj::OpenIt(){ 69 | RC rc = 0; 70 | if((rc = prevNode.OpenIt())) 71 | return (rc); 72 | return (0); 73 | } 74 | 75 | /* 76 | * Get the Data from the previous node, and reconstruct it 77 | */ 78 | RC QL_NodeProj::GetNext(char *data){ 79 | RC rc = 0; 80 | if((rc = prevNode.GetNext(buffer))) 81 | return (rc); 82 | 83 | ReconstructRec(data); 84 | return (0); 85 | } 86 | 87 | /* 88 | * Close the iterator 89 | */ 90 | RC QL_NodeProj::CloseIt(){ 91 | RC rc = 0; 92 | if((rc = prevNode.CloseIt())) 93 | return (rc); 94 | return (0); 95 | } 96 | 97 | /* 98 | * Add a projection attribute to the list of attributes to keep 99 | */ 100 | RC QL_NodeProj::AddProj(int attrIndex){ 101 | RC rc = 0; 102 | tupleLength += qlm.attrEntries[attrIndex].attrLength; 103 | 104 | attrsInRec[attrsInRecSize] = attrIndex; 105 | attrsInRecSize++; 106 | return (0); 107 | } 108 | 109 | /* 110 | * Given data from the previous node store in buffer, it reconstructs it 111 | * by retrieving only the attributes to keep, and storing the 112 | * new data in the pointer passed in 113 | */ 114 | RC QL_NodeProj::ReconstructRec(char *data){ 115 | RC rc = 0; 116 | int currIdx = 0; 117 | int *attrsInPrevNode; 118 | int numAttrsInPrevNode; 119 | if((rc = prevNode.GetAttrList(attrsInPrevNode, numAttrsInPrevNode))) 120 | return (rc); 121 | 122 | for(int i = 0; i < attrsInRecSize; i++){ 123 | int bufIdx = 0; 124 | for(int j = 0; j < numAttrsInPrevNode; j++){ 125 | if(attrsInRec[i] == attrsInPrevNode[j]){ 126 | break; 127 | } 128 | int prevNodeIdx = attrsInPrevNode[j]; 129 | bufIdx += qlm.attrEntries[prevNodeIdx].attrLength; 130 | } 131 | // get offset of index j 132 | int attrIdx = attrsInRec[i]; 133 | memcpy(data + currIdx, buffer + bufIdx, qlm.attrEntries[attrIdx].attrLength); 134 | currIdx += qlm.attrEntries[attrIdx].attrLength; 135 | } 136 | 137 | 138 | return (0); 139 | } 140 | 141 | /* 142 | * Print the node, and instruct it to print its previous nodes 143 | */ 144 | RC QL_NodeProj::PrintNode(int numTabs){ 145 | for(int i=0; i < numTabs; i++){ 146 | cout << "\t"; 147 | } 148 | cout << "--PROJ: \n"; 149 | for(int i = 0; i < attrsInRecSize; i++){ 150 | int index = attrsInRec[i]; 151 | cout << " " << qlm.attrEntries[index].relName << "." << qlm.attrEntries[index].attrName; 152 | } 153 | cout << "\n"; 154 | prevNode.PrintNode(numTabs + 1); 155 | 156 | return (0); 157 | } 158 | 159 | /* 160 | * Don't allow record returning for projection nodes 161 | */ 162 | RC QL_NodeProj::GetNextRec(RM_Record &rec){ 163 | return (QL_BADCALL); 164 | } 165 | 166 | /* 167 | * Free all memory associated with this node, and delete the previous node 168 | */ 169 | RC QL_NodeProj::DeleteNodes(){ 170 | prevNode.DeleteNodes(); 171 | delete &prevNode; 172 | if(listsInitialized == true){ 173 | free(attrsInRec); 174 | free(buffer); 175 | //free(attrsToKeep); 176 | } 177 | listsInitialized = false; 178 | return (0); 179 | } 180 | 181 | bool QL_NodeProj::IsRelNode(){ 182 | return false; 183 | } 184 | 185 | RC QL_NodeProj::OpenIt(void *data){ 186 | return (QL_BADCALL); 187 | } 188 | 189 | RC QL_NodeProj::UseIndex(int attrNum, int indexNumber, void *data){ 190 | return (QL_BADCALL); 191 | } 192 | -------------------------------------------------------------------------------- /src/ql_noderel.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: ql_noderel.cc 3 | // Description: Abstract class for query processing nodes 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | #include "comparators.h" 18 | 19 | 20 | using namespace std; 21 | 22 | /* 23 | * Create the relation node given the relation entry of the relation 24 | * it refers to 25 | */ 26 | QL_NodeRel::QL_NodeRel(QL_Manager &qlm, RelCatEntry *rEntry) : QL_Node(qlm){ 27 | relName = (char *)malloc(MAXNAME+1); 28 | memset((void *)relName, 0, sizeof(relName)); 29 | memcpy(this->relName, rEntry->relName, strlen(rEntry->relName) + 1); 30 | relNameInitialized = true; 31 | listsInitialized = false; 32 | 33 | isOpen = false; 34 | tupleLength = rEntry->tupleLength; 35 | 36 | useIndex = false; 37 | indexNo = 0; 38 | indexAttr = 0; 39 | void *value = NULL; 40 | useIndexJoin = false; 41 | } 42 | 43 | /* 44 | * Delete the memory allocated at this node 45 | */ 46 | QL_NodeRel::~QL_NodeRel(){ 47 | if(relNameInitialized == true){ 48 | free(relName); 49 | } 50 | relNameInitialized = false; 51 | if(listsInitialized == true){ 52 | free(attrsInRec); 53 | } 54 | listsInitialized = false; 55 | } 56 | 57 | /* 58 | * Open the iterator and by opening the index or filescan 59 | */ 60 | RC QL_NodeRel::OpenIt(){ 61 | RC rc = 0; 62 | isOpen = true; 63 | if(useIndex){ 64 | if((rc = qlm.ixm.OpenIndex(relName, indexNo, ih))) 65 | return (rc); 66 | if((rc = is.OpenScan(ih, EQ_OP, value))) 67 | return (rc); 68 | if((rc = qlm.rmm.OpenFile(relName, fh))) 69 | return (rc); 70 | } 71 | else{ 72 | if((rc = qlm.rmm.OpenFile(relName, fh))) 73 | return (rc); 74 | if((rc = fs.OpenScan(fh, INT, 4, 0, NO_OP, NULL))) 75 | return (rc); 76 | } 77 | return (0); 78 | } 79 | 80 | RC QL_NodeRel::OpenIt(void *data){ 81 | RC rc = 0; 82 | isOpen = true; 83 | value = data; 84 | if((rc = qlm.ixm.OpenIndex(relName, indexNo, ih))) 85 | return (rc); 86 | if((rc = is.OpenScan(ih, EQ_OP, value))) 87 | return (rc); 88 | if((rc = qlm.rmm.OpenFile(relName, fh))) 89 | return (rc); 90 | return (0); 91 | } 92 | 93 | /* 94 | * Retrieve the next record data and copy it to the pointer passed in 95 | */ 96 | RC QL_NodeRel::GetNext(char *data){ 97 | RC rc = 0; 98 | char *recData; 99 | RM_Record rec; 100 | if((rc = RetrieveNextRec(rec, recData))){ 101 | if(rc == RM_EOF || rc == IX_EOF){ 102 | return (QL_EOI); 103 | } 104 | return (rc); 105 | } 106 | memcpy(data, recData, tupleLength); 107 | return (0); 108 | } 109 | 110 | /* 111 | * Close the iterator by closing the filescan or indexscan 112 | */ 113 | RC QL_NodeRel::CloseIt(){ 114 | RC rc = 0; 115 | if(useIndex){ 116 | if((rc = qlm.rmm.CloseFile(fh))) 117 | return (rc); 118 | if((rc = is.CloseScan())) 119 | return (rc); 120 | if((rc = qlm.ixm.CloseIndex(ih ))) 121 | return (rc); 122 | } 123 | else{ 124 | if((rc = fs.CloseScan()) || (rc = qlm.rmm.CloseFile(fh))) 125 | return (rc); 126 | } 127 | isOpen = false; 128 | return (rc); 129 | } 130 | 131 | /* 132 | * Retrieves the next record by either using the index or the filescan 133 | */ 134 | RC QL_NodeRel::RetrieveNextRec(RM_Record &rec, char *&recData){ 135 | RC rc = 0; 136 | if(useIndex){ 137 | RID rid; 138 | if((rc = is.GetNextEntry(rid) )) 139 | return (rc); 140 | if((rc = fh.GetRec(rid, rec) )) 141 | return (rc); 142 | } 143 | else{ 144 | if((rc = fs.GetNextRec(rec))) 145 | return (rc); 146 | } 147 | if((rc = rec.GetData(recData))) 148 | return (rc); 149 | return (0); 150 | } 151 | 152 | /* 153 | * Retrieves the next record from this relation 154 | */ 155 | RC QL_NodeRel::GetNextRec(RM_Record &rec){ 156 | RC rc = 0; 157 | char *recData; 158 | if((rc = RetrieveNextRec(rec, recData))){ 159 | if(rc == RM_EOF || rc == IX_EOF) 160 | return (QL_EOI); 161 | return (rc); 162 | } 163 | return (0); 164 | } 165 | 166 | 167 | /* 168 | * Tells the relation node to use an index to go through the relation. 169 | * It requires the attribute number, the index number, and 170 | * the data for the the equality condition in using the index 171 | */ 172 | RC QL_NodeRel::UseIndex(int attrNum, int indexNumber, void *data){ 173 | indexNo = indexNumber; 174 | value = data; 175 | useIndex = true; 176 | indexAttr = attrNum; 177 | return (0); 178 | } 179 | 180 | /* 181 | * This node requires the list of attributes, and the number 182 | * of attributes in the relation to be set up 183 | */ 184 | RC QL_NodeRel::SetUpNode(int *attrs, int attrlistSize){ 185 | RC rc = 0; 186 | attrsInRecSize = attrlistSize; 187 | attrsInRec = (int*)malloc(attrlistSize*sizeof(int)); 188 | memset((void *)attrsInRec, 0, sizeof(attrsInRec)); 189 | for(int i = 0; i < attrlistSize; i++){ 190 | attrsInRec[i] = attrs[i]; 191 | } 192 | listsInitialized = true; 193 | 194 | return (rc); 195 | } 196 | 197 | /* 198 | * Print the node, and instruct it to print its previous nodes 199 | */ 200 | RC QL_NodeRel::PrintNode(int numTabs){ 201 | for(int i=0; i < numTabs; i++){ 202 | cout << "\t"; 203 | } 204 | cout << "--REL: " << relName; 205 | if(useIndex && ! useIndexJoin){ 206 | cout << " using index on attribute " << qlm.attrEntries[indexAttr].attrName; 207 | if(value == NULL){ 208 | cout << endl; 209 | } 210 | else{ 211 | cout << " = "; 212 | 213 | if(qlm.attrEntries[indexAttr].attrType == INT){ 214 | print_int(value, 4); 215 | } 216 | else if(qlm.attrEntries[indexAttr].attrType == FLOAT){ 217 | print_float(value, 4); 218 | } 219 | else{ 220 | print_string(value, strlen((char *)value)); 221 | } 222 | cout << "\n"; 223 | } 224 | } 225 | else if(useIndexJoin && useIndex){ 226 | cout << " using index join on attribute " < 8 | #include 9 | #include 10 | #include "redbase.h" 11 | #include "sm.h" 12 | #include "rm.h" 13 | #include "ql.h" 14 | #include "ix.h" 15 | #include 16 | #include "ql_node.h" 17 | 18 | using namespace std; 19 | 20 | /* 21 | * Initializes the state of the node 22 | */ 23 | QL_NodeSel::QL_NodeSel(QL_Manager &qlm, QL_Node &prevNode) : QL_Node(qlm), prevNode(prevNode) { 24 | isOpen = false; 25 | listsInitialized = false; 26 | tupleLength = 0; 27 | attrsInRecSize = 0; 28 | condIndex = 0; 29 | attrsInRecSize = 0; 30 | } 31 | 32 | /* 33 | * Cleans up select node 34 | */ 35 | QL_NodeSel::~QL_NodeSel(){ 36 | if(listsInitialized == true){ 37 | free(condList); 38 | free(attrsInRec); 39 | free(buffer); 40 | free(condsInNode); 41 | } 42 | listsInitialized = false; 43 | } 44 | 45 | /* 46 | * Given a max number of conditions, it makes the space to hold up to 47 | * this number of conditions. It also initializes 48 | * the attribute list for this node by copying the attribute list 49 | * of the previous node. Finally, it makes space for the 50 | * buffer which is where the record data from previous nodes 51 | * will be held. 52 | */ 53 | RC QL_NodeSel::SetUpNode(int numConds){ 54 | RC rc = 0; 55 | int *attrListPtr; 56 | if((rc = prevNode.GetAttrList(attrListPtr, attrsInRecSize))) 57 | return (rc); 58 | attrsInRec = (int *)malloc(attrsInRecSize*sizeof(int)); 59 | for(int i = 0; i < attrsInRecSize; i++){ 60 | attrsInRec[i] = attrListPtr[i]; 61 | } 62 | 63 | // allot space for these conditions 64 | condList = (Cond *)malloc(numConds * sizeof(Cond)); 65 | for(int i= 0; i < numConds; i++){ 66 | condList[i] = {0, NULL, true, NULL, 0, 0, INT}; 67 | } 68 | condsInNode = (int*)malloc(numConds * sizeof(int)); 69 | memset((void*)condsInNode, 0, sizeof(condsInNode)); 70 | 71 | prevNode.GetTupleLength(tupleLength); 72 | buffer = (char *)malloc(tupleLength); // set up buffer 73 | memset((void*)buffer, 0, sizeof(buffer)); 74 | listsInitialized = true; 75 | return (0); 76 | } 77 | 78 | 79 | 80 | /* 81 | * Open the iterator by opening the previous node 82 | */ 83 | RC QL_NodeSel::OpenIt(){ 84 | RC rc = 0; 85 | if((rc = prevNode.OpenIt())) 86 | return (rc); 87 | return (0); 88 | } 89 | 90 | /* 91 | * Get the next record 92 | */ 93 | RC QL_NodeSel::GetNext(char *data){ 94 | RC rc = 0; 95 | while(true){ 96 | if((rc = prevNode.GetNext(buffer))){ 97 | return (rc); 98 | } 99 | // keep retrieving records until the conditions are met 100 | RC cond = CheckConditions(buffer); 101 | if(cond == 0) 102 | break; 103 | } 104 | memcpy(data, buffer, tupleLength); 105 | return (0); 106 | } 107 | 108 | /* 109 | * Close the iterator by closing the previous node's iterator 110 | */ 111 | RC QL_NodeSel::CloseIt(){ 112 | RC rc = 0; 113 | if((rc = prevNode.CloseIt())) 114 | return (rc); 115 | 116 | return (0); 117 | } 118 | 119 | /* 120 | * Retrieves the next record from the previous node 121 | */ 122 | RC QL_NodeSel::GetNextRec(RM_Record &rec){ 123 | RC rc = 0; 124 | while(true){ 125 | if((rc = prevNode.GetNextRec(rec))) 126 | return (rc); 127 | 128 | char *pData; 129 | if((rc = rec.GetData(pData))) 130 | return (rc); 131 | 132 | RC cond = CheckConditions(pData); 133 | if(cond ==0) 134 | break; 135 | } 136 | 137 | return (0); 138 | } 139 | 140 | 141 | /* 142 | * Print the node, and instruct it to print its previous nodes 143 | */ 144 | RC QL_NodeSel::PrintNode(int numTabs){ 145 | for(int i=0; i < numTabs; i++){ 146 | cout << "\t"; 147 | } 148 | cout << "--SEL: " << endl; 149 | for(int i = 0; i < condIndex; i++){ 150 | for(int j=0; j ! $OUTPUT 37 | 38 | foreach queryfile ( `ls $TESTSDIR/ql_test.*` ) 39 | echo running test '#' $queryfile:e '****************' >> $OUTPUT 40 | $DBHOME/dbcreate $TESTDB 41 | $DBHOME/redbase $TESTDB < $queryfile >>& $OUTPUT 42 | $DBHOME/dbdestroy $TESTDB 43 | end 44 | 45 | # 46 | # otherwise, run just the specified tests 47 | # 48 | 49 | else 50 | foreach testnum ( $* ) 51 | if ( -r $TESTSDIR/ql_test.$testnum ) then 52 | echo running test '#' $testnum '****************' >> $OUTPUT 53 | $DBHOME/dbcreate $TESTDB 54 | $DBHOME/redbase $TESTDB < $TESTSDIR/ql_test.$testnum >>& $OUTPUT 55 | $DBHOME/dbdestroy $TESTDB 56 | else 57 | echo I can not find a test number $testnum. >> $OUTPUT 58 | endif 59 | end 60 | endif 61 | -------------------------------------------------------------------------------- /src/qo.h: -------------------------------------------------------------------------------- 1 | // 2 | // qo.h 3 | // Query Optimizer Component Interface 4 | // 5 | 6 | // This file only gives the stub for the QL component 7 | 8 | #ifndef QO_H 9 | #define QO_H 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "redbase.h" 18 | #include "parser.h" 19 | #include "rm.h" 20 | #include "ix.h" 21 | #include "sm.h" 22 | #include "ql_node.h" 23 | #include "ql.h" 24 | #undef max 25 | #include 26 | 27 | // keeps track of attribute statistics 28 | typedef struct attrStat{ 29 | float numTuples; // num distinct values for this attribute 30 | float maxValue; // maxValue for attribute 31 | float minValue; // minValue for attribute 32 | } attrStat; 33 | 34 | // keeps track of the join statistics 35 | typedef struct costElem{ 36 | int joins; // bitmap of rels in (S-a) 37 | int newRelIndex; // index of a 38 | float numTuples; // number of tuples of 39 | float cost; // cost of joining (S-a) with a to get S 40 | int indexAttr; // index attribute. is -1 if no index is used 41 | int indexCond; // index condition. is -1 if no index is used 42 | std::map attrs; // map of attribute statistics 43 | } costElem; 44 | 45 | 46 | class QO_Manager{ 47 | friend class QL_Manager; 48 | 49 | public: 50 | QO_Manager(QL_Manager &qlm, int nRelations, RelCatEntry *relations, int nAttributes, AttrCatEntry *attributes, 51 | int nConditions, const Condition conditions[]); 52 | ~QO_Manager(); 53 | // prints all the entries in optcost 54 | RC PrintRels(); 55 | 56 | // Returns the list of relations in optimal join order, and 57 | // estimated cost and tuple #s 58 | RC Compute(QO_Rel *relOrder, float &costEst, float &tupleEst); 59 | 60 | // Calculates the optimal join for joining relations in bitmap 61 | // relsInJoin 62 | RC CalculateOptJoin(int relsInJoin, int relSize); 63 | 64 | // calculates the cost/stats of joining relsInJoin and newRel 65 | RC CalculateJoin(int relsInJoin, int newRel, int relSize, float &cost, float &totalTuples, 66 | std::map &attrs,int &indexAttr, int &indexCond); 67 | 68 | // Checks whether a condition should be used for a given 69 | // set of (S-a) and a relation a 70 | RC IsValidIndexCond(int relsJoined, int condIndex, int relIdx, int &attrIndex); 71 | 72 | // Bitmap Operations 73 | RC AddRelToBitmap(int relNum, int &bitmap); 74 | RC RemoveRelFromBitmap(int relNum, int &bitmap); 75 | RC ClearBitmap(int &bitmap); 76 | bool IsBitSet(int relNum, int bitmap); 77 | // Converts bitmap to vector of ints, where vector of ints refer 78 | // to bit positions that are set 79 | RC ConvertBitmapToVec(int bitmap, std::vector &relsInJoin); 80 | RC ConvertVecToBitmap(std::vector &relsInJoin, int &bitmap); 81 | 82 | // updates optcost to contain the base cases of 1 relation 83 | RC InitializeBaseCases(); 84 | 85 | // calculates the stats 86 | RC CalcCondsForRel(std::map & attrStats, int relsInJoin, int relIdx, 87 | float &totalTuples, bool &useIdx, int& indexAttr, int&condAttr); 88 | 89 | // For each attribute in attribute stats that is not attrIdx1 or 90 | // attrIdx2, update its value to numTuples if its value is more than 91 | // numTuples 92 | RC NormalizeStats(std::map &attr_stats, float frac, float numTuples, int attrIdx1, int attrIdx2); 93 | 94 | // calculate the stats for applying different types of conditions 95 | RC ApplyEQCond(std::map& attr_stats, int condIdx, float& numTuples); 96 | RC ApplyLTCond(std::map& attr_stats, int condIdx, float& numTuples); 97 | RC ApplyGTCond(std::map& attr_stats, int condIdx, float& numTuples); 98 | 99 | RC ComputeAllSubsets(std::vector subsets, int size); 100 | // Calculate the number of GetPAge calls to filescan through 101 | // a relation given the number of tuples and tuple length 102 | float CalculateNumPages(int numTuples, int tupleLength); 103 | 104 | // Retrieves the attribute indices involve din a condition 105 | RC CondToAttrIdx(int condIndex, int &attrIdx1, int &attrIdx2); 106 | // Converts a value in a condition to a float value 107 | RC ConvertValueToFloat(int condIndex, float &value); 108 | // returns true if we are to use the condition or not for this 109 | // join calculation 110 | bool UseCondition(int relsJoined, int condIndex, int relIdx); 111 | 112 | // converts strings to floats 113 | float ConvertStrToFloat(char *string); 114 | 115 | // Given an attribute, returns the index of the relation it belongs in 116 | RC AttrToRelIndex(const RelAttr attr, int& relIndex); 117 | 118 | private: 119 | QL_Manager &qlm; // ql_manager relference 120 | int nRels; // # of rels in selection 121 | int nAttrs; // # of attributes in selection 122 | int nConds; // # of conditions in selections 123 | RelCatEntry *rels; // pointer to array of RelCatEntries for this selection 124 | AttrCatEntry *attrs; // pointer to array of AttrCatEntries for this selection 125 | // pointer to the list of conditions for this selection 126 | const Condition *conds; 127 | 128 | // optcost array for keeping track of statistics 129 | // during the dynamic programming 130 | std::vector > optcost; 131 | 132 | }; 133 | 134 | 135 | 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/redbase.cc: -------------------------------------------------------------------------------- 1 | // 2 | // redbase.cc 3 | // 4 | // Author: Jason McHugh (mchughj@cs.stanford.edu) 5 | // 6 | // This shell is provided for the student. 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "redbase.h" 13 | #include "rm.h" 14 | #include "sm.h" 15 | #include "ql.h" 16 | 17 | using namespace std; 18 | 19 | PF_Manager pfm; 20 | RM_Manager rmm(pfm); 21 | IX_Manager ixm(pfm); 22 | SM_Manager smm(ixm, rmm); 23 | QL_Manager qlm(smm, ixm, rmm); 24 | 25 | 26 | // 27 | // main 28 | // 29 | int main(int argc, char *argv[]) 30 | { 31 | char *dbname; 32 | RC rc; 33 | 34 | // Look for 2 arguments. The first is always the name of the program 35 | // that was executed, and the second should be the name of the 36 | // database. 37 | if (argc != 2) { 38 | cerr << "Usage: " << argv[0] << " dbname \n"; 39 | exit(1); 40 | } 41 | 42 | // Opens up the database folder 43 | dbname = argv[1]; 44 | if ((rc = smm.OpenDb(dbname))) { 45 | PrintError(rc); 46 | return (1); 47 | } 48 | 49 | 50 | RBparse(pfm, smm, qlm); 51 | 52 | // Closes the database folder 53 | if ((rc = smm.CloseDb())) { 54 | PrintError(rc); 55 | return (1); 56 | } 57 | 58 | 59 | cout << "Bye.\n"; 60 | } 61 | -------------------------------------------------------------------------------- /src/redbase.h: -------------------------------------------------------------------------------- 1 | // 2 | // redbase.h 3 | // global declarations 4 | // 5 | #ifndef REDBASE_H 6 | #define REDBASE_H 7 | 8 | // Please DO NOT include any other files in this file. 9 | 10 | // 11 | // Globally-useful defines 12 | // 13 | #define MAXNAME 24 // maximum length of a relation 14 | // or attribute name 15 | #define MAXSTRINGLEN 255 // maximum length of a 16 | // string-type attribute 17 | #define MAXATTRS 40 // maximum number of attributes 18 | // in a relation 19 | 20 | #define YY_SKIP_YYWRAP 1 21 | #define yywrap() 1 22 | void yyerror(const char *); 23 | 24 | // 25 | // Return codes 26 | // 27 | typedef int RC; 28 | 29 | #define OK_RC 0 // OK_RC return code is guaranteed to always be 0 30 | 31 | #define START_PF_ERR (-1) 32 | #define END_PF_ERR (-100) 33 | #define START_RM_ERR (-101) 34 | #define END_RM_ERR (-200) 35 | #define START_IX_ERR (-201) 36 | #define END_IX_ERR (-300) 37 | #define START_SM_ERR (-301) 38 | #define END_SM_ERR (-400) 39 | #define START_QL_ERR (-401) 40 | #define END_QL_ERR (-500) 41 | 42 | #define START_PF_WARN 1 43 | #define END_PF_WARN 100 44 | #define START_RM_WARN 101 45 | #define END_RM_WARN 200 46 | #define START_IX_WARN 201 47 | #define END_IX_WARN 300 48 | #define START_SM_WARN 301 49 | #define END_SM_WARN 400 50 | #define START_QL_WARN 401 51 | #define END_QL_WARN 500 52 | 53 | // ALL_PAGES is defined and used by the ForcePages method defined in RM 54 | // and PF layers 55 | const int ALL_PAGES = -1; 56 | 57 | // 58 | // Attribute types 59 | // 60 | enum AttrType { 61 | INT, 62 | FLOAT, 63 | STRING 64 | }; 65 | 66 | // 67 | // Comparison operators 68 | // 69 | enum CompOp { 70 | NO_OP, // no comparison 71 | EQ_OP, NE_OP, LT_OP, GT_OP, LE_OP, GE_OP // binary atomic operators 72 | }; 73 | 74 | // 75 | // Pin Strategy Hint 76 | // 77 | enum ClientHint { 78 | NO_HINT // default value 79 | }; 80 | 81 | // 82 | // TRUE, FALSE and BOOLEAN 83 | // 84 | #ifndef BOOLEAN 85 | typedef char Boolean; 86 | #endif 87 | 88 | #ifndef FALSE 89 | #define FALSE 0 90 | #endif 91 | 92 | #ifndef TRUE 93 | #define TRUE 1 94 | #endif 95 | 96 | #ifndef NULL 97 | #define NULL 0 98 | #endif 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/rm_error.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_error.cc 3 | // Description: RM_PrintError functions 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Yifei Huang (yifei@stanford.edu) 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "rm_internal.h" 13 | 14 | using namespace std; 15 | 16 | // 17 | // Error table 18 | // 19 | static char *RM_WarnMsg[] = { 20 | (char*)"invalid RID", 21 | (char*)"bad record size", 22 | (char*)"invalid record object", 23 | (char*)"invalid bit operation", 24 | (char*)"page is full", 25 | (char*)"invalid file", 26 | (char*)"invalid file handle", 27 | (char*)"invalid file scan", 28 | (char*)"end of page", 29 | (char*)"end of file", 30 | (char*)"invalid filename" 31 | }; 32 | 33 | static char *RM_ErrorMsg[] = { 34 | (char*)"RM error" 35 | }; 36 | 37 | // 38 | // RM_PrintError 39 | // 40 | // Desc: Send a message corresponding to a RM return code to cerr 41 | // Assumes PF_UNIX is last valid RM return code 42 | // In: rc - return code for which a message is desired 43 | // 44 | void RM_PrintError(RC rc) 45 | { 46 | // Check the return code is within proper limits 47 | if (rc >= START_RM_WARN && rc <= RM_LASTWARN) 48 | // Print warning 49 | cerr << "RM warning: " << RM_WarnMsg[rc - START_RM_WARN] << "\n"; 50 | // Error codes are negative, so invert everything 51 | else if (-rc >= -START_RM_ERR && -rc < -RM_LASTERROR) 52 | // Print error 53 | cerr << "RM error: " << RM_ErrorMsg[-rc + START_RM_ERR] << "\n"; 54 | else if (rc == PF_UNIX) 55 | #ifdef PC 56 | cerr << "OS error\n"; 57 | #else 58 | cerr << strerror(errno) << "\n"; 59 | #endif 60 | else if (rc == 0) 61 | cerr << "RM_PrintError called with return code of 0\n"; 62 | else 63 | cerr << "RM error: " << rc << " is out of bounds\n"; 64 | } 65 | -------------------------------------------------------------------------------- /src/rm_internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_internal.h 3 | // Description: Declarations internal to the record management component 4 | // Authors: Yifei Huang 5 | // 6 | 7 | #ifndef RM_INTERNAL_H 8 | #define RM_INTERNAL_H 9 | 10 | #include 11 | #include "pf.h" 12 | 13 | #define NO_MORE_FREE_PAGES -1 // for the linked list of free pages 14 | // to indicate no more free page 15 | 16 | // Define the RM page header 17 | struct RM_PageHeader { 18 | PageNum nextFreePage; 19 | int numRecords; 20 | }; 21 | 22 | #include "rm.h" 23 | 24 | #endif -------------------------------------------------------------------------------- /src/rm_manager.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_manager.cc 3 | // Description: RM_Manager handles file operations. 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | #include 7 | #include 8 | #include "pf.h" 9 | #include "rm_internal.h" 10 | 11 | 12 | RM_Manager::RM_Manager(PF_Manager &pfm) : pfm(pfm){ 13 | } 14 | 15 | RM_Manager::~RM_Manager(){ 16 | } 17 | 18 | /* 19 | * Given a filename and a record size, creates a file. RecordSize 20 | * must be a valid record size, and fileName cannot be a file that 21 | * already exists. 22 | * This function creates the file headers associated with this file 23 | */ 24 | RC RM_Manager::CreateFile (const char *fileName, int recordSize) { 25 | RC rc = 0; 26 | if(fileName == NULL) 27 | return (RM_BADFILENAME); 28 | // basic checks on record size 29 | if(recordSize <= 0 || recordSize > PF_PAGE_SIZE) 30 | return RM_BADRECORDSIZE; 31 | 32 | int numRecordsPerPage = RM_FileHandle::CalcNumRecPerPage(recordSize); 33 | int bitmapSize = RM_FileHandle::NumBitsToCharSize(numRecordsPerPage); 34 | int bitmapOffset = sizeof(struct RM_PageHeader); 35 | 36 | if( (PF_PAGE_SIZE - bitmapSize - bitmapOffset)/recordSize <= 0) 37 | return RM_BADRECORDSIZE; 38 | 39 | // Sets up the file header 40 | /* 41 | struct RM_FileHeader header; 42 | header.recordSize = recordSize; 43 | header.numRecordsPerPage = RM_FileHandle::CalcNumRecPerPage(recordSize); 44 | header.bitmapSize = RM_FileHandle::NumBitsToCharSize(header.numRecordsPerPage); 45 | header.bitmapOffset = sizeof(struct RM_PageHeader); 46 | header.numPages = 1; 47 | header.firstFreePage = NO_MORE_FREE_PAGES; 48 | 49 | // More stringent checks on record size 50 | int numRecordsPerPage = (PF_PAGE_SIZE - (header.bitmapSize) - (header.bitmapOffset))/recordSize; 51 | if(numRecordsPerPage <= 0) 52 | return RM_BADRECORDSIZE; 53 | header.numRecordsPerPage = numRecordsPerPage; 54 | */ 55 | 56 | // Creates the file 57 | if((rc = pfm.CreateFile(fileName))) 58 | return (rc); 59 | 60 | // Opens the file, creates a new page and copies the header into it 61 | PF_PageHandle ph; 62 | PF_FileHandle fh; 63 | struct RM_FileHeader *header; 64 | if((rc = pfm.OpenFile(fileName, fh))) 65 | return (rc); 66 | PageNum page; 67 | if((rc = fh.AllocatePage(ph)) || (rc = ph.GetPageNum(page))) 68 | return (rc); 69 | char *pData; 70 | if((rc = ph.GetData(pData))){ 71 | goto cleanup_and_exit; 72 | } 73 | header = (struct RM_FileHeader *) pData; 74 | header->recordSize = recordSize; 75 | header->numRecordsPerPage = (PF_PAGE_SIZE - bitmapSize - bitmapOffset)/recordSize; 76 | header->bitmapSize = bitmapSize; 77 | header->bitmapOffset = bitmapOffset; 78 | header->numPages = 1; 79 | header->firstFreePage = NO_MORE_FREE_PAGES; 80 | //memcpy(pData, &header, sizeof(struct RM_FileHeader)); 81 | 82 | // always unpin the page, and close the file before exiting 83 | cleanup_and_exit: 84 | RC rc2; 85 | if((rc2 = fh.MarkDirty(page)) || (rc2 = fh.UnpinPage(page)) || (rc2 = pfm.CloseFile(fh))) 86 | return (rc2); 87 | return (rc); 88 | } 89 | 90 | /* 91 | * Destroys a file 92 | */ 93 | RC RM_Manager::DestroyFile(const char *fileName) { 94 | if(fileName == NULL) 95 | return (RM_BADFILENAME); 96 | RC rc; 97 | if((rc = pfm.DestroyFile(fileName))) 98 | return (rc); 99 | return (0); 100 | } 101 | 102 | /* 103 | * Sets up the private variables of RM_FileHandle when opening up a file. 104 | * The function should be given a valid PF_FileHandle and pointer to 105 | * header or else an error is thrown 106 | */ 107 | RC RM_Manager::SetUpFH(RM_FileHandle& fileHandle, PF_FileHandle &fh, struct RM_FileHeader* header){ 108 | // set up the private variables 109 | memcpy(&fileHandle.header, header, sizeof(struct RM_FileHeader)); 110 | fileHandle.pfh = fh; 111 | fileHandle.header_modified = false; 112 | fileHandle.openedFH = true; 113 | 114 | // confirms that the header is valid 115 | if(! fileHandle.isValidFileHeader()){ 116 | fileHandle.openedFH = false; 117 | return (RM_INVALIDFILE); 118 | } 119 | return (0); 120 | } 121 | 122 | /* 123 | * Given a file name and a valid RM_FileHandle, opens up the file. The 124 | * given FileHandle must not already be associated with another open file 125 | */ 126 | RC RM_Manager::OpenFile (const char *fileName, RM_FileHandle &fileHandle){ 127 | if(fileName == NULL) 128 | return (RM_BADFILENAME); 129 | // if the filehandle is associated with another open file. exit immediately 130 | if(fileHandle.openedFH == true) 131 | return (RM_INVALIDFILEHANDLE); 132 | 133 | RC rc; 134 | // Open the file 135 | PF_FileHandle fh; 136 | if((rc = pfm.OpenFile(fileName, fh))) 137 | return (rc); 138 | 139 | // Gets the first page, and uses it to set up the header in fileHandle 140 | PF_PageHandle ph; 141 | PageNum page; 142 | if((rc = fh.GetFirstPage(ph)) || (ph.GetPageNum(page))){ 143 | fh.UnpinPage(page); 144 | pfm.CloseFile(fh); 145 | return (rc); 146 | } 147 | char *pData; 148 | ph.GetData(pData); 149 | struct RM_FileHeader * header = (struct RM_FileHeader *) pData; 150 | 151 | // set up and validate the header of this file 152 | rc = SetUpFH(fileHandle, fh, header); 153 | 154 | // Unpin the header page 155 | RC rc2; 156 | if((rc2 = fh.UnpinPage(page))) 157 | return (rc2); 158 | 159 | // If any errors occured, close the file! 160 | if(rc != 0){ 161 | pfm.CloseFile(fh); 162 | } 163 | return (rc); 164 | } 165 | 166 | /* 167 | * This helper function manipulates the private variables of 168 | * RM_FileHandle associated with an open file to reflect the closing 169 | * of the file. If the FileHandle is already closed, throw an error. 170 | */ 171 | RC RM_Manager::CleanUpFH(RM_FileHandle &fileHandle){ 172 | if(fileHandle.openedFH == false) 173 | return (RM_INVALIDFILEHANDLE); 174 | fileHandle.openedFH = false; 175 | return (0); 176 | } 177 | 178 | /* 179 | * This closes the a file specified by RM_FileHAndle. IT is an error to 180 | * close a RM_FileHandle that is already closed, or was never opened. 181 | * If the header of RM_FileHandle was changed, we need to update its 182 | * contents 183 | */ 184 | RC RM_Manager::CloseFile (RM_FileHandle &fileHandle) { 185 | RC rc; 186 | PF_PageHandle ph; 187 | PageNum page; 188 | char *pData; 189 | 190 | // If header was modified, put the first page into buffer again, 191 | // and update its contents, marking the page as dirty 192 | if(fileHandle.header_modified == true){ 193 | if((rc = fileHandle.pfh.GetFirstPage(ph)) || ph.GetPageNum(page)) 194 | return (rc); 195 | if((rc = ph.GetData(pData))){ 196 | RC rc2; 197 | if((rc2 = fileHandle.pfh.UnpinPage(page))) 198 | return (rc2); 199 | return (rc); 200 | } 201 | memcpy(pData, &fileHandle.header, sizeof(struct RM_FileHeader)); 202 | if((rc = fileHandle.pfh.MarkDirty(page)) || (rc = fileHandle.pfh.UnpinPage(page))) 203 | return (rc); 204 | 205 | } 206 | 207 | // Close the file 208 | if((rc = pfm.CloseFile(fileHandle.pfh))) 209 | return (rc); 210 | 211 | // Disassociate the fileHandle from an open file 212 | if((rc = CleanUpFH(fileHandle))) 213 | return (rc); 214 | 215 | return (0); 216 | } 217 | -------------------------------------------------------------------------------- /src/rm_record.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_record.cc 3 | // Description: RM_Record represents a record in a file 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | 7 | #include 8 | #include 9 | #include "pf.h" 10 | #include "rm_internal.h" 11 | 12 | 13 | RM_Record::RM_Record(){ 14 | size = INVALID_RECORD_SIZE; // initial contents of a record 15 | data = NULL; 16 | } 17 | 18 | RM_Record::~RM_Record(){ 19 | if(data != NULL) // delete any data associated with the record 20 | delete [] data; 21 | } 22 | 23 | /* 24 | * Copies contents of one RM_Record instance to another RM_Record instance 25 | */ 26 | RM_Record& RM_Record::operator= (const RM_Record &record){ 27 | if (this != &record){ 28 | if(this->data != NULL) // make sure the memory allocation is for the 29 | delete [] data; // correct size of the record 30 | this->size = record.size; 31 | this->data = new char[size]; 32 | memcpy(this->data, record.data, record.size); 33 | this->rid = record.rid; 34 | } 35 | return (*this); 36 | } 37 | 38 | /* 39 | * Retrieves the pointer to the record data, only if the 40 | * record is associated with valid record data and size 41 | */ 42 | RC RM_Record::GetData(char *&pData) const { 43 | if(data == NULL || size == INVALID_RECORD_SIZE) 44 | return (RM_INVALIDRECORD); 45 | pData = data; 46 | return (0); 47 | } 48 | 49 | /* 50 | * Retrieves the RID of a record only if the RID is valid 51 | */ 52 | RC RM_Record::GetRid (RID &rid) const { 53 | RC rc; 54 | if((rc = (this->rid).isValidRID())) 55 | return rc; 56 | rid = this->rid; 57 | return (0); 58 | } 59 | 60 | /* 61 | * Set the contents of this record object with specified data and RID. 62 | * the RID must be a valid RID. 63 | */ 64 | RC RM_Record::SetRecord(RID rec_rid, char *recData, int rec_size){ 65 | RC rc; 66 | if((rc = rec_rid.isValidRID())) 67 | return RM_INVALIDRID; 68 | if(rec_size <= 0 ) 69 | return RM_BADRECORDSIZE; 70 | rid = rec_rid; 71 | 72 | if(recData == NULL) 73 | return RM_INVALIDRECORD; 74 | size = rec_size; 75 | if (data != NULL) 76 | delete [] data; 77 | data = new char[rec_size]; 78 | memcpy(data, recData, size); 79 | return (0); 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/rm_rid.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_rid.cc 3 | // Description: rm_rid represents a RID 4 | // Author: Yifei Huang (yifei@stanford.edu) 5 | // 6 | #include "rm_rid.h" 7 | #include "rm_internal.h" 8 | 9 | RID::RID(){ 10 | page = INVALID_PAGE; // initially the RID refers to invalid page/slot 11 | slot = INVALID_SLOT; 12 | } 13 | 14 | RID::RID(PageNum pageNum, SlotNum slotNum) { 15 | page = pageNum; 16 | slot = slotNum; 17 | } 18 | 19 | RID::~RID(){} 20 | 21 | /* 22 | * Copies contents of one RID to another 23 | */ 24 | RID& RID::operator= (const RID &rid){ 25 | if (this != &rid){ 26 | this->page = rid.page; 27 | this->slot = rid.slot; 28 | } 29 | return (*this); 30 | } 31 | 32 | bool RID::operator== (const RID &rid) const{ 33 | return (this->page == rid.page && this->slot == rid.slot); 34 | } 35 | 36 | /* 37 | * Returns the page number of an RID 38 | */ 39 | RC RID::GetPageNum(PageNum &pageNum) const { 40 | //if(page == INVALID_PAGE) return RM_INVALIDRID; 41 | pageNum = page; 42 | return 0; 43 | } 44 | 45 | /* 46 | * Returns the page number of an RID o 47 | */ 48 | RC RID::GetSlotNum(SlotNum &slotNum) const { 49 | //if(slot == INVALID_SLOT) return RM_INVALIDRID; 50 | slotNum = slot; 51 | return 0; 52 | } 53 | 54 | /* 55 | * Checks that this is a valid RID 56 | */ 57 | RC RID::isValidRID() const{ 58 | if(page > 0 && slot >= 0) 59 | return 0; 60 | else 61 | return RM_INVALIDRID; 62 | } -------------------------------------------------------------------------------- /src/rm_rid.h: -------------------------------------------------------------------------------- 1 | // 2 | // rm_rid.h 3 | // 4 | // The Record Id interface 5 | // 6 | 7 | #ifndef RM_RID_H 8 | #define RM_RID_H 9 | 10 | // We separate the interface of RID from the rest of RM because some 11 | // components will require the use of RID but not the rest of RM. 12 | 13 | #include "redbase.h" 14 | 15 | // 16 | // PageNum: uniquely identifies a page in a file 17 | // 18 | typedef int PageNum; 19 | 20 | // 21 | // SlotNum: uniquely identifies a record in a page 22 | // 23 | typedef int SlotNum; 24 | 25 | 26 | // 27 | // RID: Record id interface 28 | // 29 | class RID { 30 | static const PageNum INVALID_PAGE = -1; 31 | static const SlotNum INVALID_SLOT = -1; 32 | public: 33 | RID(); // Default constructor 34 | RID(PageNum pageNum, SlotNum slotNum); 35 | ~RID(); // Destructor 36 | RID& operator= (const RID &rid); // Copies RID 37 | bool operator== (const RID &rid) const; 38 | 39 | RC GetPageNum(PageNum &pageNum) const; // Return page number 40 | RC GetSlotNum(SlotNum &slotNum) const; // Return slot number 41 | 42 | RC isValidRID() const; // checks if it is a valid RID 43 | 44 | private: 45 | PageNum page; 46 | SlotNum slot; 47 | }; 48 | 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/scan.l: -------------------------------------------------------------------------------- 1 | %{ 2 | /* 3 | * scan.l: lex spec for RQL 4 | * 5 | * Authors: Dallan Quass 6 | * Jan Jannink 7 | * 8 | * originally by: Mark McAuliffe, University of Wisconsin - Madison, 1991 9 | */ 10 | 11 | #include 12 | #include "redbase.h" /* parse.h needs the definition of real */ 13 | #include "parser_internal.h" /* y.tab.h needs the definition of NODE */ 14 | #include "y.tab.h" 15 | 16 | static int get_id(char *s); /* defined in scanhelp.c */ 17 | static char *get_qstring(char *qstring, int len); 18 | 19 | %} 20 | letter [A-Za-z] 21 | digit [0-9] 22 | num {digit}+ 23 | s_num [+\-]?{num} 24 | %x comment 25 | %x shell_cmd 26 | %% 27 | "/*" {BEGIN(comment);} 28 | [^*] {/* ignore the text of the comment */} 29 | "*/" {BEGIN(INITIAL);} 30 | \* {/* ignore *'s that aren't part of */} 31 | [ \n\t] {/* ignore spaces, tabs, and newlines */} 32 | {s_num} {sscanf(yytext, "%d", &yylval.ival); 33 | return T_INT;} 34 | {s_num}\.{num} {sscanf(yytext, "%f", &yylval.rval); 35 | return T_REAL;} 36 | {s_num}\.{num}[Ee]{s_num} {sscanf(yytext, "%f", &yylval.rval); 37 | return T_REAL;} 38 | \"([^\"\n]|(\"\"))*\" {yylval.sval = get_qstring(yytext, yyleng); 39 | return T_QSTRING;} 40 | \"([^\"\n]|(\"\"))*\n {printf("newline in string constant\n");} 41 | {letter}({letter}|{digit}|_)* {return get_id(yylval.sval = yytext);} 42 | "<" {return T_LT;} 43 | "<=" {return T_LE;} 44 | ">" {return T_GT;} 45 | ">=" {return T_GE;} 46 | "=" {return T_EQ;} 47 | "!=" {return T_NE;} 48 | "<>" {return T_NE;} 49 | ! {BEGIN(shell_cmd);} 50 | [^\n]* {yylval.sval = yytext; return T_SHELL_CMD;} 51 | \n {BEGIN(INITIAL);} 52 | [*/+\-=<>':;,.|&()] {return yytext[0];} 53 | <> {return T_EOF;} 54 | . {printf("illegal character [%c]\n", yytext[0]);} 55 | %% 56 | #include "scanhelp.c" 57 | -------------------------------------------------------------------------------- /src/scanhelp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * scanhelp.c: help functions for lexer 3 | * 4 | * Authors: Jan Jannink 5 | * Jason McHugh 6 | * 7 | * originally by: Mark McAuliffe, University of Wisconsin - Madison, 1991 8 | * 9 | * 1997 Changes: "print", "buffer", "reset" and "io" added. 10 | * 1998 Changes: "resize", "queryplans", "on" and "off" added. 11 | * 12 | * 13 | * This file is not compiled separately; it is #included into lex.yy.c . 14 | */ 15 | 16 | /* 17 | * size of buffer of strings 18 | */ 19 | #define MAXCHAR 5000 20 | 21 | /* 22 | * buffer for string allocation 23 | */ 24 | static char charpool[MAXCHAR]; 25 | static int charptr = 0; 26 | 27 | static int lower(char *dst, char *src, int max); 28 | static char *mk_string(char *s, int len); 29 | 30 | /* 31 | * string_alloc: returns a pointer to a string of length len if possible 32 | */ 33 | static char *string_alloc(int len) 34 | { 35 | char *s; 36 | 37 | if(charptr + len > MAXCHAR){ 38 | fprintf(stderr, "out of memory\n"); 39 | exit(1); 40 | } 41 | 42 | s = charpool + charptr; 43 | charptr += len; 44 | 45 | return s; 46 | } 47 | 48 | /* 49 | * reset_charptr: releases all memory allocated in preparation for the 50 | * next query. 51 | * 52 | * No return value. 53 | */ 54 | void reset_charptr(void) 55 | { 56 | charptr = 0; 57 | } 58 | 59 | /* 60 | * reset_scanner: resets the scanner after a syntax error 61 | * 62 | * No return value. 63 | */ 64 | void reset_scanner(void) 65 | { 66 | charptr = 0; 67 | yyrestart(yyin); 68 | } 69 | 70 | /* 71 | * get_id: determines whether s is a reserved word, and returns the 72 | * appropriate token value if it is. Otherwise, it returns the token 73 | * value corresponding to a string. If s is longer than the maximum token 74 | * length (MAXSTRINGLEN) then it returns NOTOKEN, so that the parser will 75 | * flag an error (this is a stupid kludge). 76 | */ 77 | static int get_id(char *s) 78 | { 79 | static char string[MAXSTRINGLEN]; 80 | int len; 81 | 82 | if((len = lower(string, s, MAXSTRINGLEN)) == MAXSTRINGLEN) 83 | return NOTOKEN; 84 | 85 | /* SM layer lexemes */ 86 | 87 | if(!strcmp(string, "create")) 88 | return yylval.ival = RW_CREATE; 89 | if(!strcmp(string, "drop")) 90 | return yylval.ival = RW_DROP; 91 | if(!strcmp(string, "table")) 92 | return yylval.ival = RW_TABLE; 93 | if(!strcmp(string, "index")) 94 | return yylval.ival = RW_INDEX; 95 | if(!strcmp(string, "load")) 96 | return yylval.ival = RW_LOAD; 97 | if(!strcmp(string, "help")) 98 | return yylval.ival = RW_HELP; 99 | if(!strcmp(string, "exit")) 100 | return yylval.ival = RW_EXIT; 101 | if(!strcmp(string, "print")) 102 | return yylval.ival = RW_PRINT; 103 | if(!strcmp(string, "set")) 104 | return yylval.ival = RW_SET; 105 | 106 | if(!strcmp(string, "and")) 107 | return yylval.ival = RW_AND; 108 | 109 | if(!strcmp(string, "into")) 110 | return yylval.ival = RW_INTO; 111 | if(!strcmp(string, "values")) 112 | return yylval.ival = RW_VALUES; 113 | 114 | 115 | /* QL layer lexemes */ 116 | if(!strcmp(string, "select")) 117 | return yylval.ival = RW_SELECT; 118 | if(!strcmp(string, "from")) 119 | return yylval.ival = RW_FROM; 120 | if(!strcmp(string, "where")) 121 | return yylval.ival = RW_WHERE; 122 | if(!strcmp(string, "insert")) 123 | return yylval.ival = RW_INSERT; 124 | if(!strcmp(string, "delete")) 125 | return yylval.ival = RW_DELETE; 126 | if(!strcmp(string, "update")) 127 | return yylval.ival = RW_UPDATE; 128 | 129 | /* IO Statistics lexemes */ 130 | if(!strcmp(string, "reset")) 131 | return yylval.ival = RW_RESET; 132 | if(!strcmp(string, "io")) 133 | return yylval.ival = RW_IO; 134 | 135 | if(!strcmp(string, "resize")) 136 | return yylval.ival = RW_RESIZE; 137 | if(!strcmp(string, "buffer")) 138 | return yylval.ival = RW_BUFFER; 139 | 140 | if(!strcmp(string, "queryplans")) 141 | return yylval.ival = RW_QUERY_PLAN; 142 | if(!strcmp(string, "on")) 143 | return yylval.ival = RW_ON; 144 | if(!strcmp(string, "off")) 145 | return yylval.ival = RW_OFF; 146 | 147 | /* unresolved lexemes are strings */ 148 | 149 | yylval.sval = mk_string(s, len); 150 | return T_STRING; 151 | } 152 | 153 | /* 154 | * lower: copies src to dst, converting it to lowercase, stopping at the 155 | * end of src or after max characters. 156 | * 157 | * Returns: 158 | * the length of dst (which may be less than the length of src, if 159 | * src is too long). 160 | */ 161 | static int lower(char *dst, char *src, int max) 162 | { 163 | int len; 164 | 165 | for(len = 0; len < max && src[len] != '\0'; ++len){ 166 | dst[len] = src[len]; 167 | if(src[len] >= 'A' && src[len] <= 'Z') 168 | dst[len] += 'a' - 'A'; 169 | } 170 | dst[len] = '\0'; 171 | 172 | return len; 173 | } 174 | 175 | /* 176 | * get_qstring: removes the quotes from a quoted string, allocates 177 | * space for the resulting string. 178 | * 179 | * Returns: 180 | * a pointer to the new string 181 | */ 182 | static char *get_qstring(char *qstring, int len) 183 | { 184 | /* replace ending quote with \0 */ 185 | qstring[len - 1] = '\0'; 186 | 187 | /* copy everything following beginning quote */ 188 | return mk_string(qstring + 1, len - 2); 189 | } 190 | 191 | /* 192 | * mk_string: allocates space for a string of length len and copies s into 193 | * it. 194 | * 195 | * Returns: 196 | * a pointer to the new string 197 | */ 198 | static char *mk_string(char *s, int len) 199 | { 200 | char *copy; 201 | 202 | /* allocate space for new string */ 203 | if((copy = string_alloc(len + 1)) == NULL){ 204 | printf("out of string space\n"); 205 | exit(1); 206 | } 207 | 208 | /* copy the string */ 209 | strncpy(copy, s, len + 1); 210 | return copy; 211 | } 212 | -------------------------------------------------------------------------------- /src/sm.h: -------------------------------------------------------------------------------- 1 | // 2 | // sm.h 3 | // Data Manager Component Interface 4 | // 5 | 6 | #ifndef SM_H 7 | #define SM_H 8 | 9 | // Please do not include any other files than the ones below in this file. 10 | 11 | #include 12 | #include 13 | #include "redbase.h" // Please don't change these lines 14 | #include "parser.h" 15 | #include "rm.h" 16 | #include "ix.h" 17 | #include "printer.h" 18 | #include "rm_rid.h" 19 | #include 20 | #include 21 | #include 22 | 23 | #define MAX_DB_NAME 255 24 | 25 | // Define the catalog entry for a relation 26 | typedef struct RelCatEntry{ 27 | char relName[MAXNAME + 1]; 28 | int tupleLength; 29 | int attrCount; 30 | int indexCount; 31 | int indexCurrNum; 32 | int numTuples; 33 | bool statsInitialized; 34 | } RelCatEntry; 35 | 36 | // Define catalog entry for an attribute 37 | typedef struct AttrCatEntry{ 38 | char relName[MAXNAME + 1]; 39 | char attrName[MAXNAME +1]; 40 | int offset; 41 | AttrType attrType; 42 | int attrLength; 43 | int indexNo; 44 | int attrNum; 45 | int numDistinct; 46 | float maxValue; 47 | float minValue; 48 | } AttrCatEntry; 49 | 50 | // This is used to specify information about an attribute 51 | // during bulk loading time 52 | typedef struct Attr{ 53 | int offset; 54 | int type; 55 | int length; 56 | int indexNo; 57 | IX_IndexHandle ih; 58 | bool (*recInsert) (char *, std::string, int); 59 | int numDistinct; 60 | float maxValue; 61 | float minValue; 62 | } Attr; 63 | 64 | // 65 | // SM_Manager: provides data management 66 | // 67 | class SM_Manager { 68 | friend class QL_Manager; 69 | static const int NO_INDEXES = -1; 70 | static const PageNum INVALID_PAGE = -1; 71 | static const SlotNum INVALID_SLOT = -1; 72 | public: 73 | SM_Manager (IX_Manager &ixm, RM_Manager &rmm); 74 | ~SM_Manager (); // Destructor 75 | 76 | RC OpenDb (const char *dbName); // Open the database 77 | RC CloseDb (); // close the database 78 | 79 | RC CreateTable(const char *relName, // create relation relName 80 | int attrCount, // number of attributes 81 | AttrInfo *attributes); // attribute data 82 | RC CreateIndex(const char *relName, // create an index for 83 | const char *attrName); // relName.attrName 84 | RC DropTable (const char *relName); // destroy a relation 85 | 86 | RC DropIndex (const char *relName, // destroy index on 87 | const char *attrName); // relName.attrName 88 | RC Load (const char *relName, // load relName from 89 | const char *fileName); // fileName 90 | RC Help (); // Print relations in db 91 | RC Help (const char *relName); // print schema of relName 92 | 93 | RC Print (const char *relName); // print relName contents 94 | 95 | RC Set (const char *paramName, // set parameter to 96 | const char *value); // value 97 | 98 | private: 99 | // Returns true if given attribute has valid/matching type and length 100 | bool isValidAttrType(AttrInfo attribute); 101 | 102 | // Inserts an entry about specified relName relation into relcat 103 | RC InsertRelCat(const char *relName, int attrCount, int recSize); 104 | 105 | // Insert an entry about specified attribute into attrcat 106 | RC InsertAttrCat(const char *relName, AttrInfo attr, int offset, int attrNum); 107 | // Retrieve the record and data associated with a relation entry. Return 108 | // error if one doesnt' exist 109 | RC GetRelEntry(const char *relName, RM_Record &relRec, RelCatEntry *&entry); 110 | 111 | // Finds the entry associated with a particular attribute 112 | RC FindAttr(const char *relName, const char *attrName, RM_Record &attrRec, AttrCatEntry *&entry); 113 | 114 | // Sets up print for DataAttrInfo from a file, printing relcat and printing attrcat 115 | RC SetUpPrint(RelCatEntry* rEntry, DataAttrInfo *attributes); 116 | RC SetUpRelCatAttributes(DataAttrInfo *attributes); 117 | RC SetUpAttrCatAttributes(DataAttrInfo *attributes); 118 | 119 | // Prepares the Attr array, which helps with loading 120 | RC PrepareAttr(RelCatEntry *rEntry, Attr* attributes); 121 | 122 | // Given a RelCatEntry, it populates aEntry with information about all its attribute. 123 | // While doing so, it also updates the attribute-to-relation mapping 124 | RC GetAttrForRel(RelCatEntry *relEntry, AttrCatEntry *aEntry, std::map > &attrToRel); 125 | // Given a list of relations, it retrieves all the relCatEntries associated with them placing 126 | // them in the list specified by relEntries. It also returns the total # of attributes in all the 127 | // relations combined, and populates the mapping from relation name to index number in relEntries 128 | RC GetAllRels(RelCatEntry *relEntries, int nRelations, const char * const relations[], 129 | int &attrCount, std::map &relToInt); 130 | 131 | // Opens a file and loads it 132 | RC OpenAndLoadFile(RM_FileHandle &relFH, const char *fileName, Attr* attributes, 133 | int attrCount, int recLength, int &loadedRecs); 134 | // Cleans up the Attr array after loading 135 | RC CleanUpAttr(Attr* attributes, int attrCount); 136 | float ConvertStrToFloat(char *string); 137 | RC PrintStats(const char *relName); 138 | RC CalcStats(const char *relName); 139 | 140 | RC PrintPageStats(); 141 | RC ResetPageStats(); 142 | 143 | IX_Manager &ixm; 144 | RM_Manager &rmm; 145 | 146 | RM_FileHandle relcatFH; 147 | RM_FileHandle attrcatFH; 148 | bool printIndex; // Whether to print the index or not when 149 | // help is called on a specific table 150 | 151 | bool useQO; 152 | 153 | bool calcStats; 154 | bool printPageStats; 155 | }; 156 | 157 | /* 158 | * 159 | */ 160 | class SM_AttrIterator{ 161 | friend class SM_Manager; 162 | public: 163 | SM_AttrIterator (); 164 | ~SM_AttrIterator (); 165 | RC OpenIterator(RM_FileHandle &fh, char *relName); 166 | RC GetNextAttr(RM_Record &attrRec, AttrCatEntry *&entry); 167 | RC CloseIterator(); 168 | 169 | private: 170 | bool validIterator; 171 | RM_FileScan fs; 172 | 173 | }; 174 | 175 | // 176 | // Print-error function 177 | // 178 | void SM_PrintError(RC rc); 179 | 180 | #define SM_CANNOTCLOSE (START_SM_WARN + 0) // invalid RID 181 | #define SM_BADRELNAME (START_SM_WARN + 1) 182 | #define SM_BADREL (START_SM_WARN + 2) 183 | #define SM_BADATTR (START_SM_WARN + 3) 184 | #define SM_INVALIDATTR (START_SM_WARN + 4) 185 | #define SM_INDEXEDALREADY (START_SM_WARN + 5) 186 | #define SM_NOINDEX (START_SM_WARN + 6) 187 | #define SM_BADLOADFILE (START_SM_WARN + 7) 188 | #define SM_BADSET (START_SM_WARN + 8) 189 | #define SM_LASTWARN SM_BADSET 190 | 191 | #define SM_INVALIDDB (START_SM_ERR - 0) 192 | #define SM_ERROR (START_SM_ERR - 1) // error 193 | #define SM_LASTERROR SM_ERROR 194 | 195 | 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/sm_attriterator.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: SM component attribute iterator 3 | // Description: This funciton keeps a scan that scans for attributes that 4 | // belong to a particular relation 5 | // Author: Yifei Huang (yifei@stanford.edu) 6 | 7 | #include 8 | #include 9 | #include "rm.h" 10 | #include "sm.h" 11 | 12 | using namespace std; 13 | 14 | SM_AttrIterator::SM_AttrIterator(){ 15 | validIterator = false; 16 | } 17 | 18 | 19 | // Closes the scan if there is one 20 | SM_AttrIterator::~SM_AttrIterator(){ 21 | if(validIterator == true){ 22 | fs.CloseScan(); 23 | } 24 | validIterator = false; 25 | 26 | } 27 | 28 | /* 29 | * Creates a scan for attributes related to a specified relation. Must 30 | * ba passed in the filehandle to attrCat 31 | */ 32 | RC SM_AttrIterator::OpenIterator(RM_FileHandle &fh, char *relName){ 33 | RC rc = 0; 34 | validIterator = true; 35 | if((rc = fs.OpenScan(fh, STRING, MAXNAME+1, 0, EQ_OP, relName))) 36 | return (rc); 37 | 38 | return (0); 39 | } 40 | 41 | /* 42 | * Returns the next attribute that it finds that is associated with 43 | * specified relation 44 | */ 45 | RC SM_AttrIterator::GetNextAttr(RM_Record &attrRec, AttrCatEntry *&entry){ 46 | RC rc = 0; 47 | if((rc = fs.GetNextRec(attrRec))) 48 | return (rc); 49 | if((rc = attrRec.GetData((char *&)entry))) 50 | return (rc); 51 | return (0); 52 | } 53 | 54 | /* 55 | * Close the scan associated with this 56 | */ 57 | RC SM_AttrIterator::CloseIterator(){ 58 | RC rc = 0; 59 | if((rc = fs.CloseScan())) 60 | return (rc); 61 | validIterator = false; 62 | return (0); 63 | } -------------------------------------------------------------------------------- /src/sm_error.cc: -------------------------------------------------------------------------------- 1 | // 2 | // File: rm_error.cc 3 | // Description: RM_PrintError functions 4 | // Authors: Hugo Rivero (rivero@cs.stanford.edu) 5 | // Dallan Quass (quass@cs.stanford.edu) 6 | // Yifei Huang (yifei@stanford.edu) 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include "sm.h" 13 | 14 | using namespace std; 15 | 16 | // 17 | // Error table 18 | // 19 | static char *SM_WarnMsg[] = { 20 | (char*)"cannot close db", 21 | (char*)"bad relation name", 22 | (char*)"bad relation specification", 23 | (char*)"bad attribute", 24 | (char*)"invalid attribute", 25 | (char*)"attribute indexed already", 26 | (char*)"attribute has no index", 27 | (char*)"invalid/bad load file", 28 | (char*)"bad set statement" 29 | }; 30 | 31 | static char *SM_ErrorMsg[] = { 32 | (char*)"Invalid database", 33 | (char*)"SM Error" 34 | }; 35 | 36 | // 37 | // RM_PrintError 38 | // 39 | // Desc: Send a message corresponding to a RM return code to cerr 40 | // Assumes PF_UNIX is last valid RM return code 41 | // In: rc - return code for which a message is desired 42 | // 43 | void SM_PrintError(RC rc) 44 | { 45 | // Check the return code is within proper limits 46 | if (rc >= START_SM_WARN && rc <= SM_LASTWARN) 47 | // Print warning 48 | cerr << "SM warning: " << SM_WarnMsg[rc - START_SM_WARN] << "\n"; 49 | // Error codes are negative, so invert everything 50 | else if (-rc >= -START_SM_ERR && -rc < -SM_LASTERROR) 51 | // Print error 52 | cerr << "SM error: " << SM_ErrorMsg[-rc + START_SM_ERR] << "\n"; 53 | else if (rc == PF_UNIX) 54 | #ifdef PC 55 | cerr << "OS error\n"; 56 | #else 57 | cerr << strerror(errno) << "\n"; 58 | #endif 59 | else if (rc == 0) 60 | cerr << "SM_PrintError called with return code of 0\n"; 61 | else 62 | cerr << "SM error: " << rc << " is out of bounds\n"; 63 | } 64 | -------------------------------------------------------------------------------- /src/statistics.cc: -------------------------------------------------------------------------------- 1 | // 2 | // statistics.cc 3 | // 4 | 5 | // This file holds the implementation for the StatisticsMgr class. 6 | // 7 | // The class is designed to dynamically track statistics for the client. 8 | // You can add any statistic that you would like to track via a call to 9 | // StatisticsMgr::Register. 10 | 11 | // There is no need to setup in advance which statistics that you want to 12 | // track. The call to Register is sufficient. 13 | 14 | // This is essentially a (poor-man's) simplified version of gprof. 15 | 16 | // Andre Bergholz, who was the TA for the 2000 offering has written 17 | // some (or maybe all) of this code. 18 | 19 | #include 20 | #include 21 | #include "statistics.h" 22 | 23 | using namespace std; 24 | 25 | // 26 | // Here are Statistics Keys utilized by the PF layer of the Redbase 27 | // project. 28 | // 29 | const char *PF_GETPAGE = "GETPAGE"; 30 | const char *PF_PAGEFOUND = "PAGEFOUND"; 31 | const char *PF_PAGENOTFOUND = "PAGENOTFOUND"; 32 | const char *PF_READPAGE = "READPAGE"; // IO 33 | const char *PF_WRITEPAGE = "WRITEPAGE"; // IO 34 | const char *PF_FLUSHPAGES = "FLUSHPAGES"; 35 | 36 | // 37 | // Statistic class 38 | // 39 | // This class will track a single statistic 40 | 41 | // 42 | // Default Constructor utilized by the templates 43 | // 44 | Statistic::Statistic() 45 | { 46 | psKey = NULL; 47 | iValue = 0; 48 | } 49 | 50 | 51 | // 52 | // Constructor utilized by the StatisticMgr class 53 | // 54 | // We are assured by the StatisticMgr that psKey_ is not a NULL pointer. 55 | // 56 | Statistic::Statistic(const char *psKey_) 57 | { 58 | psKey = new char[strlen(psKey_) + 1]; 59 | strcpy (psKey, psKey_); 60 | 61 | iValue = 0; 62 | } 63 | 64 | // 65 | // Copy constructor 66 | // 67 | Statistic::Statistic(const Statistic &stat) 68 | { 69 | psKey = new char[strlen(stat.psKey)+1]; 70 | strcpy (psKey, stat.psKey); 71 | 72 | iValue = stat.iValue; 73 | } 74 | 75 | // 76 | // Equality constructor 77 | // 78 | Statistic& Statistic::operator=(const Statistic &stat) 79 | { 80 | if (this==&stat) 81 | return *this; 82 | 83 | delete [] psKey; 84 | psKey = new char[strlen(stat.psKey)+1]; 85 | strcpy (psKey, stat.psKey); 86 | 87 | iValue = stat.iValue; 88 | 89 | return *this; 90 | } 91 | 92 | // 93 | // Destructor 94 | // 95 | Statistic::~Statistic() 96 | { 97 | delete [] psKey; 98 | } 99 | 100 | Boolean Statistic::operator==(const char *psKey_) const 101 | { 102 | return (strcmp(psKey_, psKey)==0); 103 | } 104 | 105 | // -------------------------------------------------------------- 106 | 107 | // 108 | // StatisticMgr class 109 | // 110 | // This class will track a dynamic list of statistics. 111 | // 112 | 113 | // 114 | // Register 115 | // 116 | // Register a change to a statistic. The psKey is the char* name of 117 | // the statistic to be tracked. This method will look for the statistic 118 | // name withing its list of statistics and perform the operation over the 119 | // stored value. The piValue is utilized for some of the operations. 120 | // 121 | // Note: if the statistic isn't found (as it will not be the very first 122 | // time) then it will be initialized to 0 - the default value. 123 | // 124 | RC StatisticsMgr::Register (const char *psKey, const Stat_Operation op, 125 | const int *const piValue) 126 | { 127 | int i, iCount; 128 | Statistic *pStat = NULL; 129 | 130 | if (psKey==NULL || (op != STAT_ADDONE && piValue == NULL)) 131 | return STAT_INVALID_ARGS; 132 | 133 | iCount = llStats.GetLength(); 134 | 135 | for (i=0; i < iCount; i++) { 136 | pStat = llStats[i]; 137 | if (*pStat == psKey) 138 | break; 139 | } 140 | 141 | // Check to see if we found the Stat 142 | if (i==iCount) 143 | // We haven't found it so create a new statistic 144 | // with the key psKey and initial value of 0. 145 | pStat = new Statistic( psKey ); 146 | 147 | // Now perform the operation over the statistic 148 | switch (op) { 149 | case STAT_ADDONE: 150 | pStat->iValue++; 151 | break; 152 | case STAT_ADDVALUE: 153 | pStat->iValue += *piValue; 154 | break; 155 | case STAT_SETVALUE: 156 | pStat->iValue = *piValue; 157 | break; 158 | case STAT_MULTVALUE: 159 | pStat->iValue *= *piValue; 160 | break; 161 | case STAT_DIVVALUE: 162 | pStat->iValue = (int) (pStat->iValue/(*piValue)); 163 | break; 164 | case STAT_SUBVALUE: 165 | pStat->iValue -= *piValue; 166 | break; 167 | }; 168 | 169 | // Finally, if the statistic wasn't in the original list then add it to 170 | // the list. 171 | // JASON:: Confirm that it makes a copy of the object in line 229 of 172 | // linkedlist.h. 173 | if (i==iCount) { 174 | llStats.Append(*pStat); 175 | delete pStat; 176 | } 177 | 178 | return 0; 179 | } 180 | 181 | // 182 | // Print 183 | // 184 | // Print out the information pertaining to a specific statistic 185 | RC StatisticsMgr::Print(const char *psKey) 186 | { 187 | if (psKey==NULL) 188 | return STAT_INVALID_ARGS; 189 | 190 | int *iValue = Get(psKey); 191 | 192 | if (iValue) 193 | cout << psKey << "::" << *iValue << "\n"; 194 | else 195 | return STAT_UNKNOWN_KEY; 196 | 197 | delete iValue; 198 | 199 | return 0; 200 | } 201 | 202 | 203 | // 204 | // Get 205 | // 206 | // The Get method will return a pointer to the integer value associated 207 | // with a particular statistic. If it cannot find the statistic then it 208 | // will return NULL. The caller must remember to delete the memory 209 | // returned when done. 210 | // 211 | int *StatisticsMgr::Get(const char *psKey) 212 | { 213 | int i, iCount; 214 | Statistic *pStat = NULL; 215 | 216 | iCount = llStats.GetLength(); 217 | 218 | for (i=0; i < iCount; i++) { 219 | pStat = llStats[i]; 220 | if (*pStat == psKey) 221 | break; 222 | } 223 | 224 | // Check to see if we found the Stat 225 | if (i==iCount) 226 | return NULL; 227 | 228 | return new int(pStat->iValue); 229 | } 230 | 231 | // 232 | // Print 233 | // 234 | // Print out all the statistics tracked 235 | // 236 | void StatisticsMgr::Print() 237 | { 238 | int i, iCount; 239 | Statistic *pStat = NULL; 240 | 241 | iCount = llStats.GetLength(); 242 | 243 | for (i=0; i < iCount; i++) { 244 | pStat = llStats[i]; 245 | cout << pStat->psKey << "::" << pStat->iValue << "\n"; 246 | } 247 | } 248 | 249 | // 250 | // Reset 251 | // 252 | // Reset a specific statistic. The easiest way to do this is to remove it 253 | // completely from the list 254 | // 255 | RC StatisticsMgr::Reset(const char *psKey) 256 | { 257 | int i, iCount; 258 | Statistic *pStat = NULL; 259 | 260 | if (psKey==NULL) 261 | return STAT_INVALID_ARGS; 262 | 263 | iCount = llStats.GetLength(); 264 | 265 | for (i=0; i < iCount; i++) { 266 | pStat = llStats[i]; 267 | if (*pStat == psKey) 268 | break; 269 | } 270 | 271 | // If we found the statistic then remove it from the list 272 | if (i!=iCount) 273 | llStats.Delete(i); 274 | else 275 | return STAT_UNKNOWN_KEY; 276 | 277 | return 0; 278 | } 279 | 280 | // 281 | // Reset 282 | // 283 | // Reset all of the statistics. The easiest way is to tell the linklist of 284 | // elements to Erase itself. 285 | // 286 | void StatisticsMgr::Reset() 287 | { 288 | llStats.Erase(); 289 | } 290 | 291 | -------------------------------------------------------------------------------- /src/statistics.h: -------------------------------------------------------------------------------- 1 | // 2 | // statistics.h 3 | // 4 | 5 | // This file contains the interface for the statistics class 6 | // which can be setup to dynamically track statistics within a 7 | // C++ program. 8 | 9 | // This is essentially a (poor-man's) simplified version of gprof. 10 | 11 | // My intent here is to allow the StatisticsMgr to be used with very little 12 | // setup on the part of the client. Notice that you don't need to setup 13 | // all the statistics that you will be tracking. You just Register the 14 | // statistic as you go. In the end the Print or Get methods will allow you 15 | // to report all the statistics. 16 | 17 | // Andre Bergholz, who was the TA for the 2000 offering, has written 18 | // some (or probably all) of this code. 19 | 20 | #ifndef STATISTICS_H 21 | #define STATISTICS_H 22 | 23 | // Some common definitions that might not already be set 24 | #ifndef Boolean 25 | typedef char Boolean; 26 | #endif 27 | 28 | #ifndef TRUE 29 | #define TRUE 1 30 | #endif 31 | 32 | #ifndef FALSE 33 | #define FALSE 0 34 | #endif 35 | 36 | #ifndef NULL 37 | #define NULL 0 38 | #endif 39 | 40 | #ifndef RC 41 | typedef int RC; 42 | #endif 43 | 44 | #ifndef STAT_BASE 45 | const int STAT_BASE = 9000; 46 | #endif 47 | 48 | // This include must come after the common defines 49 | #include "linkedlist.h" // Template class for the link list 50 | 51 | // A single statistic will be tracked by a Statistic class 52 | class Statistic { 53 | public: 54 | Statistic(); 55 | ~Statistic(); 56 | Statistic(const char *psName); 57 | 58 | // Copy constructor 59 | Statistic(const Statistic &stat); 60 | 61 | // Equality constructor 62 | Statistic& operator=(const Statistic &stat); 63 | 64 | // Check for equality between a Statistic and a name based upon the 65 | // names given to the current statistic. 66 | Boolean operator==(const char *psName_) const; 67 | 68 | // The name or key given to the statistic that this structure is 69 | // tracking 70 | char *psKey; 71 | 72 | // Currently, I have only allowed the statistic to track integer values. 73 | // Initial value will be 0. 74 | int iValue; 75 | }; 76 | 77 | // These are the different operations that a single statistic can undergo 78 | // duing a call to StatisticsMgr::Register. 79 | enum Stat_Operation { 80 | STAT_ADDONE, 81 | STAT_ADDVALUE, 82 | STAT_SETVALUE, 83 | STAT_MULTVALUE, 84 | STAT_DIVVALUE, 85 | STAT_SUBVALUE 86 | }; 87 | 88 | // The StatisticsMgr will track a group of statistics 89 | class StatisticsMgr { 90 | 91 | public: 92 | StatisticsMgr() {}; 93 | ~StatisticsMgr() {}; 94 | 95 | // Add a new statistic or register a change to an existing statistic. 96 | // The piValue for can be NULL, except for those operations that require 97 | // it. When adding the default value is 0 with the Stat_Operation being 98 | // performed over the initial value. 99 | RC Register(const char *psKey, const Stat_Operation op, 100 | const int *const piValue = NULL); 101 | 102 | // Get will return the value associated with a particular statistic. 103 | // Caller is responsible for deleting the memory returned. 104 | int *Get(const char *psKey); 105 | 106 | // Print out a specific statistic 107 | RC Print(const char *psKey); 108 | 109 | // Print out all the statistics tracked 110 | void Print(); 111 | 112 | // Reset a specific statistic 113 | RC Reset(const char *psKey); 114 | 115 | // Reset all of the statistics 116 | void Reset(); 117 | 118 | private: 119 | LinkList llStats; 120 | }; 121 | 122 | // 123 | // Return codes 124 | // 125 | const int STAT_INVALID_ARGS = STAT_BASE+1; // Bad Args in call to method 126 | const int STAT_UNKNOWN_KEY = STAT_BASE+2; // No such Key being tracked 127 | 128 | // 129 | // The following are specifically for tracking the statistics in the PF 130 | // component of Redbase. When statistics are utilized, these constants 131 | // will be used as the keys for the statistics manager. 132 | // 133 | extern const char *PF_GETPAGE; 134 | extern const char *PF_PAGEFOUND; 135 | extern const char *PF_PAGENOTFOUND; 136 | extern const char *PF_READPAGE; // IO 137 | extern const char *PF_WRITEPAGE; // IO 138 | extern const char *PF_FLUSHPAGES; 139 | 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /src/submit: -------------------------------------------------------------------------------- 1 | /usr/class/cs346/redbase/scripts/submit -------------------------------------------------------------------------------- /src/submit.ix: -------------------------------------------------------------------------------- 1 | ix_DOC 2 | redbase.h 3 | pf.h 4 | rm_rid.h 5 | rm.h 6 | ../lib/libpf.a 7 | ../lib/librm.a 8 | ../lib/libix.a 9 | ix.h 10 | ix_error.cc 11 | ix_indexhandle.cc 12 | ix_indexscan.cc 13 | ix_internal.h 14 | ix_manager.cc 15 | ix_test.cc 16 | ix_test_simple.cc 17 | ix_tester.cc 18 | ix_testjl.cc 19 | ix_testkpg_2.cc 20 | ix_testpark.cc 21 | Makefile 22 | comparators.h 23 | ix.h 24 | ix_internal.h 25 | linkedlist.h 26 | pf.h 27 | pf_buffermgr.h 28 | pf_hashtable.h 29 | pf_internal.h 30 | redbase.h 31 | rm.h 32 | rm_internal.h 33 | rm_rid.h 34 | rm_test.h 35 | statistics.h 36 | -------------------------------------------------------------------------------- /src/submit.ql: -------------------------------------------------------------------------------- 1 | ql_DOC 2 | redbase.cc 3 | redbase 4 | dbcreate.cc 5 | dbcreate 6 | dbdestroy.cc 7 | dbdestroy 8 | ql.h 9 | ql_error.cc 10 | ql_manager.cc 11 | ql_manager_stub.cc 12 | ql_node.cc 13 | ql_node.h 14 | ql_nodejoin.cc 15 | ql_nodeproj.cc 16 | ql_noderel.cc 17 | ql_nodesel.cc 18 | Makefile 19 | comparators.h 20 | ix.h 21 | ix_internal.h 22 | ix_error.cc 23 | ix_indexhandle.cc 24 | ix_indexscan.cc 25 | ix_internal.h 26 | ix_manager.cc 27 | linkedlist.h 28 | node_comps.h 29 | parser.h 30 | parser_internal.h 31 | pf.h 32 | pf_buffermgr.h 33 | pf_hashtable.h 34 | pf_internal.h 35 | printer.h 36 | ql.h 37 | ql_node.h 38 | redbase.h 39 | rm.h 40 | rm_internal.h 41 | rm_manager.cc 42 | rm_record.cc 43 | rm_rid.cc 44 | rm_rid.h 45 | sm_attriterator.cc 46 | sm_error.cc 47 | sm_manager.cc 48 | sm.h 49 | sm_manager 50 | statistics.h 51 | y.tab.h 52 | -------------------------------------------------------------------------------- /src/submit.rm: -------------------------------------------------------------------------------- 1 | rm_DOC 2 | redbase.h 3 | pf.h 4 | ../lib/libpf.a 5 | ../lib/librm.a 6 | rm_error.cc 7 | rm_filehandle.cc 8 | rm_filescan.cc 9 | rm.h 10 | rm_internal.h 11 | rm_manager.cc 12 | rm_record.cc 13 | rm_rid.cc 14 | rm_rid.h 15 | rm_test.cc 16 | rm_testgmf.cc 17 | rm_test.h 18 | rm_testkpg.cc 19 | rm_testrecsizes.cc 20 | rm_testshnFIXED.cc 21 | rm_testyh_random.cc 22 | Makefile 23 | linkedlist.h 24 | pf_buffermgr.cc 25 | pf_buffermgr.h 26 | pf_error.cc 27 | pf_filehandle.cc 28 | pf.h 29 | pf_hashtable.cc 30 | pf_hashtable.h 31 | pf_internal.h 32 | pf_manager.cc 33 | pf_pagehandle.cc 34 | pf_statistics.cc 35 | redbase.h 36 | rm.h 37 | rm_internal.h 38 | rm_rid.h 39 | rm_test.h 40 | statistics.h 41 | statistics.cc 42 | -------------------------------------------------------------------------------- /src/submit.sm: -------------------------------------------------------------------------------- 1 | sm_DOC 2 | redbase 3 | dbcreate 4 | dbdestroy 5 | redbase.cc 6 | dbcreate.cc 7 | dbdestroy.cc 8 | sm.h 9 | sm_attriterator.cc 10 | sm_error.cc 11 | sm_manager.cc 12 | Makefile 13 | comparators.h 14 | ix.h 15 | ix_error.cc 16 | ix_internal.h 17 | ix_indexhandle.cc 18 | ix_indexscan.cc 19 | ix_manager.cc 20 | linkedlist.h 21 | parser.h 22 | parser_internal.h 23 | pf.h 24 | pf_buffermgr.h 25 | pf_hashtable.h 26 | pf_internal.h 27 | printer.h 28 | ql.h 29 | redbase.h 30 | rm.h 31 | rm_error.cc 32 | rm_internal.h 33 | rm_rid.h 34 | rm_test.h 35 | rm_filescan.cc 36 | rm_filehandle.cc 37 | rm_manager.cc 38 | rm_record.cc 39 | rm_rid.cc 40 | sm.h 41 | statistics.h 42 | y.tab.h 43 | -------------------------------------------------------------------------------- /src/y.tab.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 2.5. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . */ 19 | 20 | /* As a special exception, you may create a larger work that contains 21 | part or all of the Bison parser skeleton and distribute that work 22 | under terms of your choice, so long as that work isn't itself a 23 | parser generator using the skeleton or a modified version thereof 24 | as a parser skeleton. Alternatively, if you modify or redistribute 25 | the parser skeleton itself, you may (at your option) remove this 26 | special exception, which will cause the skeleton and the resulting 27 | Bison output files to be licensed under the GNU General Public 28 | License without this special exception. 29 | 30 | This special exception was added by the Free Software Foundation in 31 | version 2.2 of Bison. */ 32 | 33 | 34 | /* Tokens. */ 35 | #ifndef YYTOKENTYPE 36 | # define YYTOKENTYPE 37 | /* Put the tokens into the symbol table, so that GDB and other debuggers 38 | know about them. */ 39 | enum yytokentype { 40 | RW_CREATE = 258, 41 | RW_DROP = 259, 42 | RW_TABLE = 260, 43 | RW_INDEX = 261, 44 | RW_LOAD = 262, 45 | RW_SET = 263, 46 | RW_HELP = 264, 47 | RW_PRINT = 265, 48 | RW_EXIT = 266, 49 | RW_SELECT = 267, 50 | RW_FROM = 268, 51 | RW_WHERE = 269, 52 | RW_INSERT = 270, 53 | RW_DELETE = 271, 54 | RW_UPDATE = 272, 55 | RW_AND = 273, 56 | RW_INTO = 274, 57 | RW_VALUES = 275, 58 | T_EQ = 276, 59 | T_LT = 277, 60 | T_LE = 278, 61 | T_GT = 279, 62 | T_GE = 280, 63 | T_NE = 281, 64 | T_EOF = 282, 65 | NOTOKEN = 283, 66 | RW_RESET = 284, 67 | RW_IO = 285, 68 | RW_BUFFER = 286, 69 | RW_RESIZE = 287, 70 | RW_QUERY_PLAN = 288, 71 | RW_ON = 289, 72 | RW_OFF = 290, 73 | T_INT = 291, 74 | T_REAL = 292, 75 | T_STRING = 293, 76 | T_QSTRING = 294, 77 | T_SHELL_CMD = 295 78 | }; 79 | #endif 80 | /* Tokens. */ 81 | #define RW_CREATE 258 82 | #define RW_DROP 259 83 | #define RW_TABLE 260 84 | #define RW_INDEX 261 85 | #define RW_LOAD 262 86 | #define RW_SET 263 87 | #define RW_HELP 264 88 | #define RW_PRINT 265 89 | #define RW_EXIT 266 90 | #define RW_SELECT 267 91 | #define RW_FROM 268 92 | #define RW_WHERE 269 93 | #define RW_INSERT 270 94 | #define RW_DELETE 271 95 | #define RW_UPDATE 272 96 | #define RW_AND 273 97 | #define RW_INTO 274 98 | #define RW_VALUES 275 99 | #define T_EQ 276 100 | #define T_LT 277 101 | #define T_LE 278 102 | #define T_GT 279 103 | #define T_GE 280 104 | #define T_NE 281 105 | #define T_EOF 282 106 | #define NOTOKEN 283 107 | #define RW_RESET 284 108 | #define RW_IO 285 109 | #define RW_BUFFER 286 110 | #define RW_RESIZE 287 111 | #define RW_QUERY_PLAN 288 112 | #define RW_ON 289 113 | #define RW_OFF 290 114 | #define T_INT 291 115 | #define T_REAL 292 116 | #define T_STRING 293 117 | #define T_QSTRING 294 118 | #define T_SHELL_CMD 295 119 | 120 | 121 | 122 | 123 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 124 | typedef union YYSTYPE 125 | { 126 | 127 | /* Line 2068 of yacc.c */ 128 | #line 71 "parse.y" 129 | 130 | int ival; 131 | CompOp cval; 132 | float rval; 133 | char *sval; 134 | NODE *n; 135 | 136 | 137 | 138 | /* Line 2068 of yacc.c */ 139 | #line 140 "y.tab.h" 140 | } YYSTYPE; 141 | # define YYSTYPE_IS_TRIVIAL 1 142 | # define yystype YYSTYPE /* obsolescent; will be withdrawn */ 143 | # define YYSTYPE_IS_DECLARED 1 144 | #endif 145 | 146 | extern YYSTYPE yylval; 147 | 148 | 149 | --------------------------------------------------------------------------------