This commit is contained in:
jackfoxy 2023-05-21 21:24:31 -07:00
parent 1ba1bc82ca
commit 83cdf09388
9 changed files with 340 additions and 74 deletions

View File

@ -1,6 +1,7 @@
# Types
All data representations (nouns) of the Obelisk system are strongly typed.
## Column Types
The fundamental data element is an atom typed by an aura.
All data cells (the intersection of a `<table-set>` row and column) are a typed atom.
@ -35,8 +36,17 @@ Obelisk supports the following auras:
|@uw|unsigned base-64|0wx5~J|
|@ux|unsigned hexadecimal|0x84.5fed|
All datasets in Obelisk are sets, meaning each typed element only exists once.
They are also commonly regarded as tables, meaning the index of each cell (row/column intersenction) can be calculated.
Columns are typed by an aura and indexed by name.
```
<column-type> ::=
<aura/name>
```
## Table Row and Table Types
All datasets in Obelisk are sets, meaning each typed element (the `<row-type>`) only exists once.
They are also commonly regarded as tables, but this is only true when the index of each cell (row/column intersenction) can be calculated, and this is only true when the `SELECT` statement includes and `ORDER BY` clause.
All tables either are, or derive from, base-tables spawned by `CREATE TABLE`.
Base-table (`<table>`) rows have exactly one type, the table's atomic aura-typed columns in a fixed order.
@ -44,26 +54,33 @@ Base-table (`<table>`) rows have exactly one type, the table's atomic aura-typed
<row-type> ::=
list <aura>
```
Columns are sets typed by an aura and indexed by name.
```
<column-type> ::=
<aura/name>set
```
Each base-table is itself typed by its `<row-type>`.
```
<table-type> ::=
<row-type>list
(list <row-type>)
```
Base-table definitions include a unique primary ordering of rows, hence it has list type, not set type. This is not the case for every other instance of `<table-set>`.
Rows from `<view>`s, `<common-table-expression>`'s, and command output from `<transform>`, or any other table that is not a base-table can only have an immutable row ordering, if it was so specified (i.e. the `SELECT` statement has an `ORDER BY` clause). In general all these other tables have types that are unions of `<row-type>`s.
When the `<table-set-type>` is a union of `<row-type>`s there is a `<row-type>` that represents the full width of the SELECT statement and as many `<row-type>` sub-types as necessary to represent any unjoined LEFT or RIGHT JOINs that resulted in a row.
Sub-types are column-wise aligned with the all-column `<row-type>`, regardless of how the SELECT statement is constructed.
In general `<table-set>`s have the type:
```
<table-set-type> ::=
<row-type>list
| set set <row-type>
(list <row-type>)
| (set (<all-column-row-type> | <row-sub-type-1> | ... | <row-sub-type-n> ))
```
Rows from `<view>`s, `<common-table-expression>`'s, and command output from `<transform>`, or any other table that is not a base-table can only have an immutable row ordering, if it was so specified (i.e. the `SELECT` statement has an `ORDER BY` clause). In general all these other tables have types are unions of `<row-type>`s.
All the other static types in Obelisk are defined in sur/ast/hoon.
## Other Types
All the static types in Obelisk API are defined in sur/ast/hoon.
## Remarks
Ultimately even `<table>` rows are typed as sets, not lists, once they are referenced in a statement because statements can generally choose column ordering.
Ultimately even `<table>`s can be typed as sets, because `SELECT` without `ORDER BY` has undefined row order.
On the other hand, regardless of the presence of `ORDER BY` any `<table-set>` emitted by any step in a `<transform>` is a list of `<row-type>` in some (possibly arbitrary) order.
And ultimately "set" is the most important concept because every `<table-set>` will have one unique row value for any given `sub-type` of `<row-type>`.

View File

@ -1,38 +1,54 @@
# CREATE DATABASE
Creates a new user-space database available to any agent running on the ship. There is no sand-boxing.
```
CREATE DATABASE <database-name>
```
Example:
## Example
```
<create-database> ::=
CREATE DATABASE my-database
```
API:
## API
```
+$ create-database $:([%create-database name=@t])
+$ create-database $:([%create-database name=@tas])
```
## Arguments
**`<database-name>`**
User-defined name for the new database. Must follow the hoon term naming standard.
## Remarks
`CREATE DATABASE` must be the only command in a script. The script will fail if there are prior commands. As the first command it will succeed and subsequent commands will be ignored.
The command results in a state change of the Obelisk agent.
`CREATE DATABASE` must be the only command in a script.
The script will fail if there are prior commands.
As the first command it will succeed and subsequent commands will be ignored.
## Produced Metadata
INSERT `name`, `<timestamp>` into `sys.sys.databases`
Creates all `<database>.sys` tables.
## Exceptions
database already exists
# CREATE INDEX
Creates an index over selected column(s) on an existing table.
```
<create-index> ::=
CREATE [ UNIQUE ] [ NONCLUSTERED | CLUSTERED ] INDEX <index-name>
ON [ <db-qualifer> ]{ <table-name> | <view-name> }
ON [ <db-qualifer> ] <table-name>
( <column-name> [ ASC | DESC ] [ ,...n ] )
```
Examples:
## Examples
```
CREATE INDEX ix_vendor-id ON product-vendor (vendor-id);
CREATE UNIQUE INDEX ix_vendor-id2 ON dbo.product-vendor
@ -40,12 +56,8 @@ CREATE UNIQUE INDEX ix_vendor-id2 ON dbo.product-vendor
CREATE INDEX ix_vendor-id3 ON purchasing..product-vendor (vendor-id);
```
Discussion:
Index name cannot start with 'pk-' as these names are internally reserved for primary keys.
A table or view can only have up to one `CLUSTERED` index, including the primary key for tables.
The `UNIQUE` option is not available for views.
## API
API:
```
+$ create-index
$:
@ -58,29 +70,74 @@ API:
==
```
## Arguments
**`<index-name>`**
User-defined name for the new index. Must follow the hoon term naming standard.
**`<table-name>`**
Name of existing table the index targets.
If not explicitly qualified defaults to the agent's current database and 'dbo' namespace.
**`<column-name> [ ASC | DESC ] [ ,...n ] `**
List of column names in the target table, representing the sort hierarchy, and optionally sort direction for each level, defaulting to `ASC`, ascending.
## Remarks
The command results in a state change of the Obelisk agent.
Index name cannot start with 'pk-' as these names are internally reserved for primary keys.
Index name cannot start with 'fk-' as these names are internally reserved for primary keys.
TO DO: investigate hoon ordered maps to determine what exactly "clustered" means in hoon. It may be that multiple clustering indices are possibley, freaking out most DBAs.
## Produced Metadata
# Exceptions
INSERT `table name`, `namespace` `index-name`, `NONCLUSTERED | CLUSTERED`, `is-unique`, `<timestamp>` into `<database>.sys.indices`
## Exceptions
index name already exists for table
table does not exist
column does not exist
UNIQUE specified and existing values are not unique for the column(s) specified
index name begins with 'pk-' or 'fk-'
# CREATE NAMESPACE
Namespaces provide a means of grouping database components including tables and views.
When not otherwise specified namepace designations default to `dbo`.
```
<create-namespace> ::=
CREATE NAMESPACE [<database-name>.]<namespace-name>
```
Example:
## Example
`CREATE NAMESPACE my-namespace`
API:
## API
```
+$ create-namespace $:([%create-namespace database-name=@t name=@t])
```
## Arguments
**`<namespace-name>`**
User-defined name for the new index. Must follow the hoon term naming standard.
The namespace "sys" is reserved for system use.
## Remarks
The command results in a state change of the Obelisk agent.
## Produced Metadata
INSERT `name`, `<timestamp>` into `<database>.sys.namespaces`
## Exceptions
namespace already exists
# CREATE PROCEDURE
Procedures are urQL scripts that accept parameters.
```
<create-proc> ::=
@ -90,13 +147,16 @@ API:
AS { <urql command>; | *hoon } [ ;...n ]
```
Discussion:
## Remarks
TBD
Cannot be used to create database.
# CREATE TABLE
Tables are the only means of indexed persistent `<table-sets>`s.
Any update to `<table>` contents results in an agent state change.
TO DO: any reason to specify foreign key name (see CREATE INDEX).
```
<create-table> ::=
CREATE TABLE
@ -105,27 +165,22 @@ Cannot be used to create database.
[ ,... n ] )
PRIMARY KEY [ NONCLUSTERED | CLUSTERED ] ( <column-name> [ ,... n ] )
[ { FOREIGN KEY <foreign-key-name> ( <column-name> [ ASC | DESC ] [ ,... n ] )
REFERENCES [ <namespace-name>. ] <table-name> ( <column-name> [ ,... n ]
[ ON DELETE { NO ACTION | CASCADE } ]
[ ON UPDATE { NO ACTION | CASCADE } ] }
REFERENCES [ <namespace-name>. ] <table-name> ( <column-name> [ ,... n ] )
[ ON DELETE { NO ACTION | CASCADE | SET DEFAULT } ]
[ ON UPDATE { NO ACTION | CASCADE | SET DEFAULT } ] }
[ ,... n ] ]`
```
Example:
## Example
```
CREATE TABLE order-detail
(invoice-nbr @ud, line-item @ud, product-id @ud, special-offer-id @ud, message @t)
PRIMARY KEY CLUSTERED (invoice-nbr, line-item)
FOREIGN KEY fk-special-offer-order-detail (productid, specialofferid)
FOREIGN KEY fk-special-offer-order-detail (product-id, specialoffer-id)
REFERENCES special-offer (product-id, special-offer-id)
```
Discussion:
`PRIMARY KEY` must be unique.
`SET NULL` only applies to columns defined as `unit`. Columns defined otherwise will be treated as the default `NO ACTION`.
`SET DEFAULT` applies the column's default constant, if available, otherwise the bunt of the aura.
API:
## API
```
+$ create-table
$:
@ -137,39 +192,143 @@ API:
==
```
## Arguments
**`<table-name>`**
User-defined name for the new table. Must follow the hoon term naming standard.
If not explicitly qualified defaults to the agent's current database and 'dbo' namespace.
**`<column-name> <aura>`**
List of user-define column names and associated auras. Names must follow the hoon term naming standard.
See [ref-ch02-types](ref-ch02-types.md)
**`[ NONCLUSTERED | CLUSTERED ] ( <column-name> [ ,... n ]`**
Columns in the required unique primary index. Defining the index as `CLUSTERED` is optional.
**`<foreign-key-name> ( <column-name> [ ASC | DESC ] [ ,... n ]`**
User-defined name for `<foreign-key>`. Must follow the hoon term naming standard.
List of columns in the table for association with a foreign table along with sort ordering. Default is `ASC` ascending.
**`<table-name> ( <column-name> [ ,... n ]`**
Referenced foreign `<table>` and columns. Count and associated column auras must match the specified columns from the new `<table>`.
**`ON DELETE { NO ACTION | CASCADE | SET DEFAULT }`**
Specifies an action on the rows in the table if those rows have a referential relationship and the referenced row is deleted from the foreign table.
* NO ACTION (default)
The agent raises an error and the delete action on the row in the parent foreign table is rolled back.
* CASCADE
Corresponding rows are deleted from the referencing table when that row is deleted from the parent foreign table.
* SET DEFAULT
All the values that make up the foreign key are set to their bunt values when the corresponding row in the parent foreign table is deleted.
The agent raises an error if the parent table has no entry with bunt values.
**`ON UPDATE { NO ACTION | CASCADE | SET DEFAULT }`**
Specifies an action on the rows in the table if those rows have a referential relationship and the referenced row is deleted from the foreign table.
* NO ACTION (default)
The Database Engine raises an error, and the update action on the row in the parent table is rolled back.
* CASCADE
Corresponding rows are updated in the referencing table when that row is updated in the parent table.
* SET DEFAULT
All the values that make up the foreign key are set to their bunt values when the corresponding row in the parent table is updated.
The agent raises an error if the parent table has no entry with bunt values.
## Remarks
The command results in a state change of the Obelisk agent.
`PRIMARY KEY` is unique.
TO DO: What constitutes `CLUSTERED` in hoon? An ordered map? This will shake-out during development.
## Produced Metadata
INSERT `table name`, `namespace`, `<timestamp>` INTO `<database>.sys.tables`
INSERT `table name`, `namespace`, `<ordinal>`, `column name`, `aura`, `<timestamp>` INTO `<database>.sys.table-columns`
INSERT `table name`, `namespace`, `delete | update`, `<action>`, `<timestamp>` INTO `<database>.sys.table-ref-integrity`
CREATE INDEX on Primary Key
CREATE INDEX on Foreign Keys
## Exceptions
name within namespace already exists for table
table referenced by FOREIGN KEY does not exist
table column referenced by FOREIGN KEY does not exist
aura mis-match in FOREIGN KEY
# CREATE TRIGGER
A trigger automatically runs when a specified event occurs in the agent. It runs a previously defined `<procedure>`.
An `INSTEAD OF` trigger fires before the triggering event can occur and replaces it. Otherwise the procedure runs after the triggering event succedes and all state changed by both the triggering event and trigger `<procedure>` is included in one and the same state change.
Trigger events are INSERT, UPDATE, or DELETE statements on a `<table>`.
The trigger event for a `<view>` is simple execution.
```
<create-trigger> ::=
CREATE TRIGGER [ <db-qualifer> ]<trigger-name>
ON { <table-name> | <view-name> }
[ ENABLE | DISABLE ]
{ AFTER | INSTEAD OF }
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
AS <procedure>
[ ENABLE | DISABLE ]
```
TBD hoon triggers
Discussion:
Not for initial release.
## Remarks
TBD
could be used to trigger any database process or agent
`{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }` does not apply to views.
# CREATE VIEW
A view creates a `<table-set>` whose contents (columns and rows) are defined by a `<transform>`.
Potential caching of views is TBD.
```
<create-view> ::=
CREATE VIEW [ <db-qualifer> ]<view-name> AS <transform>
```
Discussion:
Views are read only.
When a column is derived from an arithmetic expression, a function, or a constant; or when two or more columns may otherwise have the same name, typically because of a JOIN; distinct column names must be assigned in the SELECT statement using AS. Otherwise view columns acquire the same names as the columns in the SELECT statement.
API:
## API
```
+$ create-view
$:
%create-view
view=qualified-object
query=query
query=transform
==
```
## Arguments
**`<view-name>`**
User-defined name for the new view. Must follow the hoon term naming standard.
**`<transform>`**
`<transform>` producing the output `<table-set>`.
## Remarks
The command results in a state change of the Obelisk agent.
Views are read only.
The last step of the `<transform>` must establish unique column names, whether inherited from prior `<table-set>`s or aliased columns.
## Produced Metadata
INSERT `name`, `<transform>`, `<timestamp>` into `sys.sys.views`
INSERT `name`, `<ordinal>`, `<column>` into `sys.sys.view-columns`
## Exceptions
view already exists

View File

@ -12,8 +12,7 @@ Deletes rows from a `<table-set>`.
DELETE [ FROM ] <table-set>
[ WHERE <predicate> ]
```
API:
## API
```
+$ delete
$:
@ -22,8 +21,15 @@ API:
predicate=(unit predicate)
==
```
## Arguments
** **
## Remarks
The command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
A stand-alone `DELETE` statement can only operate on a `<table>` and produces a `<transform>` of one command step with no CTEs.
When `<table-set>` is a `<table>` the command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
@ -50,7 +56,7 @@ Inserts rows into a `<table-set>`.
INSERT INTO <table-set>
[ ( <column> [ ,...n ] ) ]
{ VALUES (<scalar-expression> [ ,...n ] ) [ ,...n ]
| <query> }
| <transform> }
```
```
@ -62,9 +68,9 @@ Inserts rows into a `<table-set>`.
| expression <binary-operator> expression }
```
TBD see functions chapter, still undergoing design development.
`<scalar-function>` TBD, see functions chapter undergoing design development.
API:
## API
```
+$ insert
$:
@ -75,8 +81,14 @@ API:
==
```
## Arguments
** **
## Remarks
The command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
A stand-alone `INSERT` statement can only operate on a `<table>` and produces a `<transform>` of one command step with no CTEs.
When `<table-set>` is a `<table>` the command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
@ -87,9 +99,15 @@ When `<table-set>` is a virtual table the command produces an output `<table-set
The `VALUES` or `<query>` must provide data for all columns in the expected order.
Cord values are represented in single quotes 'this is a cord'.
Cord values are represented in single quotes `'this is a cord'`.
Escape single quotes with double backslash thusly `'this is a cor\\'d'`.
When `( <column> [ ,...n ] )` not specified, inserted columns must be arranged in same order as target `<table-set>`.
When target `<table-set>` is a `<table>` input `<row-type>` must match the `<table>` `<row-type>`.
When target `<table-set>` is not a `<table>` and the input is from a `<transform>` then the target `<table-set>` and `<transform>` `<table-set>` must have the same all-column `<row-type>`. New `<row-type>` sub-types may be introduced.
## Produced Metadata
@@ROWCOUNT returns the total number of rows inserted
@ -97,6 +115,7 @@ Escape single quotes with double backslash thusly `'this is a cor\\'d'`.
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
colum misalignment
# TRUNCATE TABLE
@ -108,7 +127,7 @@ Removes all rows in a base table.
TRUNCATE TABLE [ <ship-qualifer> ] <table>
```
API:
## API
```
+$ truncate-table
$:
@ -116,6 +135,11 @@ API:
table=qualified-object
==
```
## Arguments
** **
## Remarks
The command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
@ -142,7 +166,7 @@ Changes content of selected columns in existing rows of a `<table-set>`.
[ WHERE <predicate> ]
```
API:
## API
```
+$ update
$:
@ -154,8 +178,14 @@ API:
==
```
## Arguments
** **
## Remarks
The command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.
A stand-alone `UPDATE` statement can only operate on a `<table>` and produces a `<transform>` of one command step with no CTEs.
When `<table-set>` is a `<table>` the command potentially mutates `<table>` and if so results in a state change of the Obelisk agent.

View File

@ -120,7 +120,7 @@ See CH 8 Functions for full documentation on Scalars.
[ [ <ship-qualifer> ]<table-view> | <alias> ].<column-name>
```
API:
## API
```
+$ query
$:
@ -135,5 +135,9 @@ API:
==
```
## Arguments
** **
## Exceptions

View File

@ -68,6 +68,21 @@ USING <source-table> [ [ AS ] <alias> ]
| NOP
```
## API
```
+$ merge
$:
%merge
target-table=table-set
new-table=(unit table-set)
source-table=table-set
predicate=predicate
matched=(list matching)
unmatched-by-target=(list matching)
unmatched-by-source=(list matching)
==
```
## TO DO: evaluate decision tree of target/source singleton/union type
## Arguments
@ -237,20 +252,6 @@ e) For 1 (one) ≤ i ≤ NI, the Syntax Rules of Subclause 9.2, “Store assignm
as VALUE and the column of table T identified by the i-th <column name> in the <insert column list>
as TARGET.
API:
```
+$ merge
$:
%merge
target-table=table-set
new-table=(unit table-set)
source-table=table-set
predicate=predicate
matched=(list matching)
unmatched-by-target=(list matching)
unmatched-by-source=(list matching)
==
```
## Exceptions

View File

@ -62,6 +62,14 @@ API:
==
```
## Arguments
** **
## Remarks
## Produced Metadata
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated

View File

@ -1,5 +1,7 @@
# Functions
**IMPORTANT NOTE**: the design of functions is still on-going. Nothing is implemented in the parser and take the following as preliminary design work.
Urql has two kinds of functions.
Scalar functions take one or more columns as parameters from a single intermediary data row and return a single scalar value. Scalar functions must be declared after the `CTEs` and `FROM` clauses and before the `SELECT` clause. The user-assigned scalar name may be used in any predicate or `SELECT` clause.

View File

@ -8,9 +8,13 @@ GRANT { ADMINREAD | READONLY | READWRITE }
| [<db-qualifer>]{<view-name> | <table-name> }
```
Example:
## Example
`GRANT READONLY TO ~sampel-palnet ON my-namespace`
## Arguments
** **
Discussion:
Grantees `PARENT` and `SIBLINGS` are only valid for moon servers. `MOONS` is only valid for moon parents.
`ADMINREAD` grants read-only access to the servers administration tables and views
@ -25,3 +29,7 @@ REVOKE { ADMINREAD | READONLY | READWRITE | ALL }
| NAMESPACE [<database-name>]<namespace-name>
| [<db-qualifer>]{<view-name> | <table-name> }
```
## Arguments
** **

View File

@ -7,9 +7,18 @@ ON { <table-name> | <view-name> }
{ REBUILD | DISABLE | RESUME}
```
## Arguments
** **
Discussion:
`RESUME` will rebuild the index if the underlying object is dirty.
## Remarks
## Produced Metadata
## Exceptions
# ALTER NAMESPACE
@ -18,9 +27,18 @@ ALTER NAMESPACE [ <database-name>. ]<namespace-name>
TRANSFER { TABLE | VIEW } [ <db-qualifer> ]{ <table-name> | <view-name> }
```
## Arguments
** **
Discussion:
The namespace *sys* cannot be altered, nor can objects be transferred in or out of it.
## Remarks
## Produced Metadata
## Exceptions
# ALTER PROCEDURE
@ -56,6 +74,15 @@ ALTER TABLE my-table
DROP FOREIGN KEY fk-1, fk-2
```
## Arguments
** **
## Remarks
## Produced Metadata
## Exceptions
# ALTER TRIGGER
@ -76,3 +103,13 @@ ALTER VIEW [ <db-qualifer> ]{ <view-name> }
( { [<alias>.] <column-name> } [ ,...n ] )
AS <select_statement>
```
## Arguments
** **
## Remarks
## Produced Metadata
## Exceptions