|
Managing the database is done through "DDL" commands. In SIRA_PRISE, these commands are nothing else than regular assignment commands to catalog relvars. Two particular consequences from this approach deserve to be spelled out explicitly :
- Just like all regular assignments, they are set-level, and it is thus possible to define multiple relvars, multiple dbms files, multiple attributes, ... in one single assignment command.
- Just as with regular assignment, multiple assignment to distinct target relvars is also possible, and in fact in certain cases it is even required, due to the database constraints that govern the catalog. Nevertheless, lots of combinations of catalog MA may not be supported (especially the ones that
involve assignments which define or modify the physical design of some part of the database), most often because the corresponding side-effects cannot be applied to the system properly. Also remember that assignments must always be either to catalog relvars or else to 'user' relvars. It is e.g. not possible to
define a new relvar and assign a non-empty value to it within the same statement.
Also note that, in contrast with assignments to "user" relvars, assignments to catalog relvars are always immediately committed. That is, all assignments to catalog relvars are treated as if they were made from a connection/transaction that has its 'autocommit' flag set to true.
The DDL commands will now be discussed one by one, and any relevant remarks given as appropriate. For all updatable catalog relvars, one section will be presented with the concerned relvar's name as the section title. In the sections, the heading of the relvar will be specified as well as that relvar's
keys, unless the relvar is all-key (every attribute participates in the only key).
-
Defining Types
The first step in defining a new database is, of course, to define its logical design. This involves deciding on which data types will be used in the database to represent the information it is supposed to contain. A number of types are
already provided by SIRA_PRISE, but it is unlikely that these will suffice to satisfy all your requirements. At times, you may want or need to define your own custom type. Three ways are available in SIRA_PRISE to achieve that :
- Java-backed types.
When creating java-backed types, the first thing to do is of course to create an implementation class in java for your type. Rules for this implementation class are to be followed both for the class name and the package name :
- The classname must be the word 'Dbms', followed by the capitalized name of the type, followed by the word "Implementation". "Capitalized name" means : first character uppercase, all other characters lowercase. E.g. the classname for the java type implementation corresponding to a
type you want to name SphericAngle, would be DbmsSphericangleImplementation.
- The package name must be either the system's type implementations package be.SIRAPRISE.typeimplementations, or else it may be a name of your choice, but in that case this package name must be included in the implementations search-path configuration setting.
- The type implementation class must implement the TypeImplementation interface.
- The type names cannot end with the word 'interval'. SIRA_PRISE automatically generates types with such names for all types that have a comparison operator GT. Also consider that the name of the corresponding intervaltype, that is automatically generated by SIRA_PRISE if the type has an
ordering operator, must itself also obey the rules for typenames, in particular the maximum length for typenames. This means that the maximum length for names of types that have an ordering operator, is only 52, not 60. See the last paragraphs of this section for more information on interval
types.
Obviously, the compiled class must also be made available on the server's classpath. When that is done, you can register your type by adding a tuple to the JavaBackedType relvar.
- User-defined types
SIRA_PRISE also offers the possibility of defining custom types without providing a java implementation for the type. Naming such a type is done by adding the required tuples to the UserDefinedType relvar and its
"satellites".
- Constrained Types
SIRA_PRISE also offers support for (a subset of) the inheritance model depicted in TTM. Using this feature is done by adding tuples to the the ConstrainedType
relvar.
Some more things are to be said on the correspondance between any of the three foregoing "types of type", and interval types.
Whenever the system must load any type, it also tries to find an implementation for the ordering operator for that type (i.e. GT() ). If it does find such an implementation, then SIRA_PRISE automatically also defines an intervaltype, based on the ordered base type concerned and the ordering operator found for
it. The name of this intervaltype will be the name of the ordered base type, suffixed with the word "Interval". E.g. the interval type corresponding to ordered base type INT will be named INTINTERVAL. The intervaltype will itself be a scalar, unordered type. For all such interval types, a whole host of
useful operators are also automatically provided. These operators are discussed in the section on the interval operators.
The interval types themselves will have at least one possrep, which corresponds to the closed-open notation specifically. There is always a BEGIN component in this possrep, which denotes the interval's (inclusive) start point. Optionally, there is also an END component, which denotes the
interval's (non-inclusive) end point. Interval values without an END component "stretch to infinity", so to speak, i.e. they include all the values of the underlying point type up to and including the very last. Interval values that include and END component only include the values of the underlying
point type up to, but not including, this END component value. Intervals without a BEGIN component are not supported. So intervals cannot be made to "start at negative infinity", so to speak.
Some interval types will be "generated" with a second possrep, which corresponds to the closed-closed notation. This possrep has two components, FROM and TO (and these components are always present for any value of such interval types). The FROM component value is always equal to the
BEGIN component value of the "closed-open" possrep, the TO component will denote the highest value of the underlying point type that is still included in the interval's range. This second "closed-closed" possrep is generated only if all of the following conditions are met :
- A (niladic) FIRSTxxx operator can be found, with xxx the name of the underlying point type
- A (niladic) LASTxxx operator can be found, with xxx the name of the underlying point type
- A (monadic) NEXT operator can be found that takes a single argument of the underlying point type, and returns a value of the underlying point type
- A (monadic) PRIOR operator can be found that takes a single argument of the underlying point type, and returns a value of the underlying point type
One more or less special interval value is the empty interval (which, in the approach adopted by SIRA_PRISE, is indeed a valid interval value). It can be recognised (if and when it appears anywhere - which it really shouldn't) by the fact that the END component is equal to the BEGIN component.
BEGIN(1)END(1) and BEGIN(2)END(2) are thus all representations of the same -empty- interval value. The empty interval will never appear anywhere as a value of an attribute inside a relation, tuples with empty interval values are always automatically discarded from the relation.
Deleting a type will also delete the corresponding intervaltype based on the deleted type, if such an intervaltype exists. It is not possible to delete only the intervaltype based on some ordered base type, only the base type itself can be deleted, which will have the effect of removing both from
SIRA_PRISE's type system.
-
Defining operators
If you want to be able to write expressions to do computations on values of the types you have defined, you will need some operators. SIRA_PRISE comes with a set of system-provided operators, but for operating on values of your own types, you will have to implement
your own. Much as with JavaBackedType implementations, all that is needed, is to write a java class and install this in the classpath of the Java virtual machine that runs SIRA_PRISE. The details for creating such an operator implementation are specified in the javadoc.
-
Defining attributes
The next step in defining a logical design, is to define the attributes that will be used in it. In SIRA_PRISE, this must be done as a separate step, prior to defining/declaring relvars and their headings. This encourages uniform and consistent use of the same attribute names for the same "business
information" : it helps avoid multiple distinct names popping up for the same kind of info, such as "customerid", "clientid", "custid", ...
Defining attributes ("business elements") is done by adding tuples to the Attribute relvar and its "satellites".
-
Defining the logical model - relvars
When the needed business elements have been defined as attributes, the next step is to define the (logical structure of the) relvars in the database. SIRA_PRISE supports two "kinds" of relvars :
- "Base" relvars. These relvars are the "basic information bricks" in the database, and are, in principle, user-updatable ("in principle", because constraints can be defined to rule out user updates). Base relvars are defined by adding tuples to the Relvar and RelvarAttribute relvars.
- "Virtual relvars". These relvars constitute read-only views on the "Base" relvars, these relvars are therefore not updatable, in the sense that they cannot directly be the target of a database update statement. Virtual relvars are defined by adding tuples to the Virtualrelvar relvar.
-
Defining the logical model - constraints
When the relvars in the database have been defined, the constraints that apply to them can also be defined. Although all in all, any constraint is really just a constraint, SIRA_PRISE offers several distinct ways to define them :
- Keys. Keys are constraints that define a uniqueness property within a single relvar, which can be either a base relvar or a virtual one. Keys are defined by adding tuples to the Key and KeyAttribute relvars.
- Tuple constraints. Tuple constraints are constraints stating a rule that must be adhered to by all the individual tuples in a relvar (i.e. deciding that the constraint is satisfied can be done by looking at the tuple in isolation, and at nothing else). Tuple constraints are
defined by adding tuples to the TupleConstraint relvar.
- Database constraints. Database constraints are all the rules that say whether a database value is valid or not, and which are neither keys nor tuple constraints. (But note that there is no obligation for stating, say, tuple constraints as tuple constraints. They can equivalently be
defined as database constraints without any harm, but this might be
- Assignment constraints. While the three foregoing "classes" (insofar as that term is appropriate) of constraint all apply to (i.e. constrain a) single database state, assignment constraints are constraints that can depend on more than just a single database state alone. Transition
constraints, for example, which depend on both the pre-update and post-update state of the database, are supported in the form of assignment constraints. Constraints which depend on contextual information such as current date or identity of the user owning the transaction that is issuing an update, are
also supported using this concept of assignment constraints. Iow, assignment constraints are, in a sense, the "broadest" category of constraints conceivable in a database context. Defining assignment constraints is done by adding tuples to the AssignmentConstraint relvar.
The two "major purposes" for assignment constraints are : (a) to define transition constraints, and (b) to define update secruity rules. For more information on how to use
assignment constraints for enforcing update security rules, please see "securing your databases with SIRA_PRISE".
All constraints in the system, regardless of which of the 4 foregoing "categories" they belong to, are uniquely identified by an ERRORCODE. That is, the same ERRORCODE attribute value cannot appear for both a KEY and a DATABASECONSTRAINT, or any such combination.
For all constraints in the system, it is possible to define a "tailored" constraint message text. This is the text to be displayed (returned to the client) by the system as an error message, whenever it finds that a constraint is violated. Using this feature is done by manipulating the ConstraintMessageText relvar.
-
Defining the logical model - automatic ('triggered') data actions
SIRA_PRISE supports the concept of update operations to some relvar being "triggered" ("fired", as it were) by the fact of an update operation being applied to some other relvar. Using this feature is done by adding tuples to the TriggeredDataAction relvar.
-
Defining the physical model - creating the resources
For a logical design to be implemented through some physical design, the physical resources used in that design must be created. This is done by manipulating the DbmsFile relvar, the StorageSpace relvar, and its "satellites".
-
Defining the physical model - defining a physical design
With a logical design completed and the needed physical resources created, you can go about defining the physical design of your database to SIRA_PRISE. This is done by manipulating the RecordType relvar and its
"satellites", and the Index relvar and its "satellites".
-
Managing database statistics
SIRA_PRISE offers support for collecting and managing database statistics. Collecting database statistics is done using the appropriate Monitor Command. The statistics themselves are registered in the RelvarCardinality and AttributeValueDistribution relvars.
|