The code files that we have given you for the DBMS programming assignment can be grouped into several collections of related files. Some files appear in more than one collection. Below, we discuss each collection in turn.
More detail can be found in the API documentation for the framework.
Files that define and implement the parser
sym.java
Parser.java
Lexer.java
You do not need to understand the code in these files, and you will not be modifying them.
Files related to WHERE
clause evaluation
ConditionalExpression.java
AndExpression.java
OrExpression.java
NotExpression.java
TrueExpression.java
Comparison.java
CompareTerm.java
You will not be modifying these files, and you don’t need to
understand all of the details of the code that they
contain. However, you may want to browse through the files to get
some sense of how WHERE
clause evaluation is carried out.
In a parsed SQL command, a WHERE
clause is essentially a tree data
structure. For example, the WHERE
clause
WHERE age < 30 AND (zip = '02138' OR zip = '02140')
would form a tree that looks like this:
A WHERE
clause is represented by a reference to the object that
serves as the root of the WHERE
clause tree. This object is an
instance of one of the subclasses of the abstract class
ConditionalExpression
. To evaluate the clause, we simply invoke
the root object’s isTrue()
method, which returns true
if the
expression is true for the current values of the columns involved,
and false
otherwise. The leaf nodes of the tree are terms that
are being compared. These terms are either columns or literal
values. The CompareTerm
class is used for literal values. The
Column
class is used for columns; it is a subclass of
CompareTerm
.
We have given you almost all of the code needed for evaluating
WHERE
clauses. The one exception is the code you will write to
retrieve the value of a column from the tuple that is currently
being considered for selection. However, this value-retrieval code
will be implemented in other files.
Files for classes of objects generated by the parser
SQLStatement.java
(and its subclasses; more on them later)Table.java
Column.java
ColumnOptions.java
Limit.java
The SQL parser takes the SQL command entered by the user (a string of characters) and breaks it up into a set of tokens. Each token represents one element of the command — a table name, a column name, a column value, etc.
In our framework, these tokens are represented by objects, and the
tokens for a given command are managed by an object that
represents the command as a whole. For example, if the user enters
a SELECT
command, the parser will generate an object of type
SelectStatement
, and we will use that object to access the
objects that represent the individual tokens of that command
(e.g., the names of the table or tables on which the SELECT
command is operating).
The objects that represent the command as a whole are instances of
one of the subclasses of the abstract class SQLStatement
. These
subclasses will be described in the next section. The classes used
for the tokens include the classes mentioned above (Table
,
Column
, ColumnOptions
, Limit
), the classes for conditional
expressions mentioned in the previous section, and several
built-in Java classes (String
, Integer
, Double
). All
SQLStatement
subclasses have methods that allow you to get
information about the tokens of a particular type (e.g.,
getTable()
, getColumn()
, numTables()
, numColumns()
,
etc.). These accessor methods are defined in the SQLStatement
class itself, and the subclasses inherit them.
Files for classes of objects that represent SQL commands
BeginStatement.java
(for BEGIN TRANSACTION
)CommitStatement.java
(for COMMIT TRANSACTION
)CreateStatement.java
DeleteStatement.java
DropStatement.java
InsertStatement.java
RollbackStatement.java
(for ROLLBACK TRANSACTION
)SelectStatement.java
UpdateStatement.java
These files contain the class definitions for the subclasses of the
abstract class SQLStatement
that was mentioned above. Each subclass
represents one type of SQL command.
The SQLStatement
superclass includes an abstract method called
execute()
. Each subclass has its own version of that method,
that performs the operations needed to carry out that command. We
have given you the execute()
method for CREATE TABLE
and DROP
TABLE
commands. You will complete the execute()
methods of some
of the other types of SQL commands.
Files for classes of objects that are used to access and manipulate the contents of a table
Table.java
Column.java
InsertRow.java
TableIterator.java
RowOutput.java
RowInput.java
The Table
and Column
classes are used for two different
purposes. First, they are used to represent tokens generated by
the parser, in which case they primarily serve as identifiers that
specify the name of the table or column (see section 3
above). Second, they are used to represent the stored
representations of actual tables and columns in the relational
database. If the parser generates an instance of one of these
classes, it may be necessary to fill in some of the fields of the
object before it can used to actually represent a stored table or
column. You should not need to add to or modify these two classes,
but it is important that you understand the methods that they
contain. You should at least read the comments that precede
each method, and you may also want to look over the bodies of the
methods to get some idea of how they work.
InsertRow
objects are used to marshall the values in a row that
is being inserted, turning them into a single key/data pair.
You will implement the key method in this class. In doing so,
you will use objects of type RowOutput
to prepare the byte arrays
for the key/value pair that you ask Berkeley DB to store.
TableIterator
objects are used to iterate over some or all of
the tuples in a table. You will implement some of the methods in
this class. In doing so, you will use objects of type RowInput
to extract values from the byte arrays that form the basis of the
key/value pairs that you obtain from Berkeley DB.
You should not need to add to or modify the
RowOutput
or RowInput
classes, but it is important that you
understand the methods that they contain! In the case of
RowOutput
, you should also review the methods that it inherits
from the DataOutputStream
class.
Files that implement the DBMS infrastructure
DBMS.java
Catalog.java
Table.java
DBMS.java
contains the main()
method for the application. It
also has methods/functions for initializing and shutting down the
DBMS, including code for configuring and opening the Berkeley DB
environment used for the underlying BDB databases.
Catalog.java
contains the code implementing the DBMS catalog, which
stores the per-table metadata associated with each table in the DBMS.
Table.java
includes support for an in-memory table cache,
which keeps track of all tables whose underlying Berkeley DB
databases have already been opened. When a table is opened, the
corresponding Table
object is stored in this cache for possible
future use. The table cache is implemented using an instance of
Java’s HashTable
class.
You should not need to modify these files, but it is important that you understand the methods that they contain. You should at least read the comments that precede each method, and you may also want to look over the bodies of the methods to get some idea of how they work.
Note: To allow access to the DBMS
and Catalog
methods from
all other classes, we make all of these methods static, so that
the class name can be used to invoke them (e.g.,
Catalog.putMetadata(tablename);
).
Last updated on September 15, 2024.