docs contd

This commit is contained in:
jackfoxy 2024-01-07 10:03:24 -08:00
parent 59c043bfa6
commit caae6f402c
17 changed files with 579 additions and 558 deletions

View File

@ -2,7 +2,7 @@
## Introduction
A _first principles_ approach should guide the design and implementation of an Urbit RDBMS. The _urQL_ language, influenced by _The Third Manifesto_ (Date and Darwen), emphasizes composability and type safety. The areas where SQL design was hurried or neglected in terms of theoretical considerations (like nullable columns) have been excluded or corrected, making urQL closer to the _Query Language_ that Codd and Date would have endorsed.
A _first principles_ approach should guide the design and implementation of an Urbit RDBMS. The _urQL_ language, influenced by _The Third Manifesto_ (Darwen and Date), emphasizes composability and type safety. The areas where SQL design was hurried or neglected in terms of theoretical considerations (like nullable columns) have been excluded or corrected, making urQL closer to the _Query Language_ that Codd and Date would have endorsed.
An Urbit-native RDBMS implementation presents new opportunities for composability. Any desk's data is readily available for _mash up_ apps and _ad hoc_ queries, and every desk persisting data to an RDBMS already has search functionality built-in.
@ -26,17 +26,15 @@ Functions, apart from the simplest ones, are grouped in their own clause and inl
Inlined sub-queries are prohibited to enhance readability. JOINs and/or CTEs accommodate all related use cases and promote composability. CTEs can be referenced for certain use cases in predicates.
Relational division is supported with a DIVIDED BY operator.
Relational division is supported with a DIVIDED BY operator. (not yet implemented in the urQL parser or Obelisk)
Set operations support nesting of queries on the right side of the operator.
All data manipulation commands (DELETE, INSERT, MERGE, UPDATE), along with the SELECT statement, can accept a dataset output by the previous TRANSFORM step and send its output dataset to the next step.
All data manipulation commands (DELETE, INSERT, MERGE, UPDATE), along with the SELECT statement, can accept a dataset output by the previous TRANSFORM step and send its output dataset to the next step. (experimental; not yet implemented in the urQL parser of Obelisk and may not be)
Reading and/or updating data on foreign ships is permissible if the ship's pilot has granted permission. Cross database joins are allowed, but cross ship joins are not. Views cannot be defined on foreign databases.
Reading and/or updating data on foreign ships is permissible if the ship's pilot has granted permission. Cross database joins are allowed, but cross ship joins are not. Views cannot be defined on foreign databases. (not yet implemented in Obelisk)
Queries can operate on previous versions and data of the databases through the the AS OF clause.
This document has placeholders for Stored Procedures and Triggers, which have yet to be defined. These will be points for integration with hoon and other agents.
Queries can operate on previous versions and data of the databases through the the AS OF clause. (not yet implemented in the urQL parser or Obelisk)
## urQL language diagrams and general syntax
@ -101,7 +99,7 @@ Each CTE is always referenced by alias, never inlined.
When `<view>, <table>` have the same name within a namespace, `<view>` is said to "shadow" `<table>` wherever syntax accepts `<table>` or `<view>`.
A base-tables, `<table>`, are the sole source of content in an Obelisk database and the only manifestation of `<table-set>` that is not a computation.
Base-tables, `<table>`, are the sole source of content in an Obelisk database and the only manifestation of `<table-set>` that is not a computation.
The `<transform>` command returns a `<table-set>`, hence every `<table-set>` is typed by one or more equivalent urQL `<transform>` commands. This is true because every `<transform>` command is idempotent. (More on this in the section on __Time__.)
@ -112,10 +110,19 @@ The row type is defined by the component columns and may be a union type. Hence
AS OF { NOW
| <timestamp>
| n { SECONDS | MINUTES | HOURS | DAYS | WEEKS | MONTHS | YEARS } AGO
| <inline-scalar>
| <time-offset>
}
```
Specifying `<as-of-time>` overrides setting the schema and/or content timestamp in state changes. See the section on __Time__.
`NOW` default, current computer time
`<timestamp>` any valid time in @da format
`n ... AGO` sets the schema and/or content timestamp in state changes back from `NOW` according to the time units specified.
`<time-offset>` any valid timespan in @dr format; sets the schema and/or content timestamp in state changes back from `NOW`.
## Literals
@ -255,3 +262,7 @@ Even `<table>`s can be typed as sets, because a `SELECT` statement without an `O
Regardless of the presence of `ORDER BY`, any `<table-set>` emitted by any step in a `<transform>`, a CTE, or a `<view>` is a list of `<row-type>` in some (possibly arbitrary) order.
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>`.
## Time
In **urQL** time is both primary and fundamental. Every change of state, whether to a database's schema or content, is indexed by time. Thus every query is idempotent.

View File

@ -41,7 +41,7 @@ If not explicitly qualified, it defaults to the Obelisk agent's current database
**`<column> <aura>`**
The list of user-defined column names and associated auras. Names must adhere to the hoon term naming standard.
For more details, refer to [ref-ch02-types](ref-ch02-types.md)
For more details, refer to [01-preliminaries](01-preliminaries.md)
**`[ CLUSTERED | LOOK-UP ] ( <column> [ ,... n ]`**
These are column names in the required unique primary index. Defining the index as `LOOK-UP` is optional.

179
docs/05-ddl-index Normal file
View File

@ -0,0 +1,179 @@
(currently supported in urQL parser, likely to be revised, not yet supported in Obelisk)
# CREATE INDEX
This command creates an index over selected column(s) of an existing table.
```
<create-index> ::=
CREATE [ UNIQUE ] [ LOOK-UP | CLUSTERED ] INDEX <index>
ON [ <db-qualifer> ] <table>
( <column> [ ASC | DESC ] [ ,...n ] )
```
## Examples
```
CREATE INDEX ix_vendor-id ON product-vendor (vendor-id);
CREATE UNIQUE INDEX ix_vendor-id2 ON dbo.product-vendor
(vendor-id DESC, name ASC, address DESC);
CREATE INDEX ix_vendor-id3 ON purchasing..product-vendor (vendor-id);
```
## API
```
+$ create-index
$:
%create-index
name=@t
object-name=qualified-object :: because index can be over table or view
is-unique=?
is-clustered=?
columns=(list ordered-column)
==
```
## Arguments
**`UNIQUE`**
Specifies that no two rows are permitted to have the same index key value.
**`LOOK-UP | CLUSTERED`**
`CLUSTERED` creates an index in which the logical order of the key values determines the physical order of the corresponding rows in a table. A `<table>` or `<view>` can have only one clustered index at a time.
**`<index>`**
User-defined name for the new index. This name must follow the Hoon term naming standard.
**`<table>`**
Name of existing table the index targets.
If not explicitly qualified, defaults to the Obelisk agent's current database and 'dbo' namespace.
**`<column> [ ASC | DESC ] [ ,...n ] `**
List of column names in the target table. This list represents the sort hierarchy and optionally specifies the sort direction for each level. The default sorting is `ASC` (ascending).
## Remarks
This command mutates the state of the Obelisk agent.
Index names cannot start with 'pk-' or 'fk-' as these prefixes are reserved for primary keys and foreign keys respectively.
_NOTE_: Further investigation is required to determine how "clustering" works in Hoon.
## Produced Metadata
## Example
INSERT `table name`, `namespace` `index-name`, `LOOK-UP | 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-'
# ALTER INDEX
Modifies the structure of an existing `<index>` on a user `<table>` or `<view>`.
```
<alter-index> ::=
ALTER [ UNIQUE ] [ NONCLUSTERED | CLUSTERED ] INDEX [ <db-qualifer> ]<index>
ON { <table> | <view> }
[ ( <column> [ ASC | DESC ] [ ,...n ] ) ]
{ DISABLE | RESUME}
```
## API
```
+$ alter-index
$:
%alter-index
name=qualified-object
object=qualified-object
columns=(list ordered-column)
action=index-action
==
```
## Arguments
**`UNIQUE`**
Specifies that no two rows are permitted to have the same index key value.
**`NONCLUSTERED | CLUSTERED`**
`CLUSTERED` creates an index in which the logical order of the key values determines the physical order of the corresponding rows in a table. A `<table>` or `<view>` can have only one clustered index at a time.
**`[ <db-qualifer> ]<index>`**
Specifies the target index.
**`<table> | <view>`**
Name of the underlying object of the index.
**`<column> [ ASC | DESC ] [ ,...n ] `**
List of column names in the target table. This list represents the sort hierarchy and optionally specifies the sort direction for each level. The default sorting is `ASC` (ascending).
**`DISABLE | RESUME`**
Used to disable an active index or resume a disabled index.
## Remarks
This command mutates the state of the Obelisk agent.
Cannot alter primary key and foreign key indices.
`RESUME` will rebuild the index if the underlying object is dirty.
Note: Further investigation into hoon ordered maps is needed to determine what exactly "clustered" means in hoon.
## Produced Metadata
update `<database>.sys.indices`
## Exceptions
index name does not exist for table
table does not exist
column does not exist
UNIQUE specified and existing values are not unique for the column(s) specified
# DROP INDEX
Deletes an existing `<index>`.
```
<drop-index> ::=
DROP INDEX <index>
ON [ <db-qualifer> ] { <table> | <view> }
```
## API
```
+$ drop-index
$:
%drop-index
name=@tas
object=qualified-object
==
```
## Arguments
**`<index>`**
The name of the index to delete.
**`<table> | <view>`**
`<table>` or `<view>` with the named index.
## Remarks
This command mutates the state of the Obelisk agent.
Indexes with names that begin with "pk-" cannot be dropped, as these are table primary keys.
This command can be used to delete a `<foreign-key>`.
If `<view>` is shadowing `<table>`, the system attempts to find `<index>` on `<view>` first, then `<table>`.
## Produced Metadata
DELETE FROM `<database>.sys.indices`
DELETE FROM `<database>.sys.table-ref-integrity`
## Exceptions
`<table>` or `<view>` does not exist
`<index>` does not exist on `<table>` or `<view>`.

View File

@ -1 +0,0 @@
..

77
docs/06-insert.md Normal file
View File

@ -0,0 +1,77 @@
# INSERT
Inserts rows into a `<table-set>`.
```
<insert> ::=
INSERT INTO <table-set>
[ ( <column> [ ,...n ] ) ]
{ VALUES (<scalar-expression> [ ,...n ] ) [ ...n ]
| <transform> }
[ <as-of-time> ]
```
```
<scalar-expression> ::=
{ <constant>
| TBD }
```
Currently only constants are supported as `VALUES`.
## API
```
+$ insert
$:
%insert
table=qualified-object
columns=(unit (list @t))
values=insert-values
==
```
## Arguments
**`<table-set>`**
The target of the `INSERT` operation.
**`<column>` [ ,...n ]**
When present, the column list must account for all column identifiers (names or aliases) in the target once. It determines the order in which update values are applied and the output `<table-set>`'s column order.
**(`<scalar-expression>` [ ,...n ] ) [ ,...n ]**
Row(s) of literal values to insert into target. Source auras must match target columnwise.
**`<transform>`**
Transform creating source `<table-set>` to insert into target. Source auras must match target columnwise.
## Remarks
When `<table-set>` is a `<table>` the command potentially mutates `<table>`, resulting in a state change of the Obelisk agent.
When `INSERT` operates on a `<table>`, it must be in the terminal (last) step of a `<transform>` or a stand-alone `INSERT`.
Data in the *sys* namespace cannot be inserted into.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
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'`. Single quotes within cord values must be escaped with double backslash as `'this is a cor\\'d'`.
If `( <column> [ ,...n ] )` is not specified, the inserted columns must be arranged in the same order as the target `<table-set>`.
When the target `<table-set>` is a `<table>`, the 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.
Note that multiple parentheses enclosed rows of column values are NOT comma separated.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows inserted
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
unique key violation
colum misalignment

View File

@ -1 +0,0 @@
..

59
docs/07-update.md Normal file
View File

@ -0,0 +1,59 @@
# UPDATE
(currently supported in urQL parser, not yet supported in Obelisk)
Changes content of selected columns in existing rows of a `<table-set>`.
```
<update> ::=
UPDATE [ <ship-qualifier> ] <table-set>
SET { <column> = <scalar-expression> } [ ,...n ]
[ WHERE <predicate> ]
[ <as-of-time> ]
```
## API
```
+$ update
$:
%update
table=qualified-object
columns=(list @t)
values=(list value-or-default)
predicate=(unit predicate)
==
```
## Arguments
**`<table-set>`**
The target of the `UPDATE` operation.
**`<column>` = `<scalar-expression>`**
`<column>` is a column name or alias of a target column. `<scalar-expression>` is a valid expression within the statement context.
**`<predicate>`**
Any valid `<predicate>`, including predicates on CTEs.
## Remarks
When `<table-set>` is a `<table>`, the command potentially mutates the data within `<table>`, resulting in a state change of the Obelisk agent.
A stand-alone `UPDATE` statement can only operate on a `<table>`, producing a `<transform>` of one command step with no CTEs.
Data in the *sys* namespace cannot be updated.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
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'. Single quotes within cord values must be escaped with double backslash as `'this is a cor\\'d'`.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows updated
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
unique key violation
aura mismatch on `SET`

46
docs/08-delete Normal file
View File

@ -0,0 +1,46 @@
# DELETE
(currently supported in urQL parser, not yet supported in Obelisk)
Deletes rows from a `<table-set>`.
```
<delete> ::=
DELETE [ FROM ] <table-set>
[ WHERE <predicate> ]
[ <as-of-time> ]
```
## API
```
+$ delete
$:
%delete
table=qualified-object
predicate=(unit predicate)
==
```
## Arguments
**`<table-set>`**
The target of the `DELETE` operation.
**`<predicate>`**
Any valid `<predicate>`, including predicates on CTEs.
## Remarks
When `<table-set>` is a `<table>`, the command potentially mutates `<table>` resulting 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.
Data in the *sys* namespace cannot be deleted.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
## Produced Metadata
@@ROWCOUNT returns the total number of rows deleted
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated

38
docs/09-truncate-table Normal file
View File

@ -0,0 +1,38 @@
# TRUNCATE TABLE
(currently supported in urQL parser, not yet supported in Obelisk)
Removes all rows in a base table.
```
<truncate-table> ::=
TRUNCATE TABLE [ <ship-qualifier> ] <table>
[ <as-of-time> ]
```
## API
```
+$ truncate-table
$:
%truncate-table
table=qualified-object
==
```
## Arguments
**`<table>`**
The target table.
## Remarks
The command potentially mutates `<table>`, resulting in a state change of the Obelisk agent.
Tables in the *sys* namespace cannot be truncated.
## Produced Metadata
none
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated

152
docs/10-query Normal file
View File

@ -0,0 +1,152 @@
(currently supported in urQL parser, likely to be revised, under development in Obelisk)
# QUERY
The `<query>` statement provides a means to create `<table-set>`s derived from persisted and/or cached `<table-set>`s and/or constants. Data rows can be joined based on predicates, specific columns can be selected, and the resulting rows can be filtered by predicate.
```
<query> ::=
[ FROM <table-set> [ [AS] <alias> ]
{
{ JOIN | LEFT JOIN | RIGHT JOIN | OUTER JOIN }
<table-set> [ [AS] <alias> ]
ON <predicate>
} [ ...n ]
| CROSS JOIN <table-set> [ [AS] <alias> ]
]
[ WHERE <predicate> ]
[ GROUP BY { <qualified-column>
| <column-alias>
| <column-ordinal> } [ ,...n ]
[ HAVING <predicate> ]
]
SELECT [ TOP <n> ] [ BOTTOM <n> ]
{ * | { [<ship-qualifier>]<table-view> | <alias> }.*
| <expression> [ [ AS ] <column-alias> ]
} [ ,...n ]
[ ORDER BY
{
{ <qualified-column> | <column-alias> | <column-ordinal> } { ASC | DESC }
} [ ,...n ]
]
```
`JOIN` is an inner join returning all matching pairs of rows.
`LEFT JOIN` is a left outer join returning all rows from the left table not meeting the join condition, along with all matching pairs of rows.
`RIGHT JOIN` is a right outer join returning all rows from the right table not meeting the join condition, along with all matching pairs of rows.
`OUTER JOIN` is a full outer join returning matching pairs of rows, as well as all rows from both tables not meeting the join condition.
`CROSS JOIN` is a cartesian join of two tables.
Cross database joins are permitted, but not cross ship joins.
`HAVING <predicate>` filters aggregated rows returned from the `<query>`. The column references in the predicate must be either one of the grouping columns or be contained in an aggregate function.
Avoid using `ORDER BY` in CTEs or in any query prior to the last step in a `<transform>`, unless required by `TOP` or `BOTTOM` specified in the `SELECT` statement or, in the case of CTEs, it is used in an `<expression>` expecting a scalar result.
```
<predicate> ::=
{ [ NOT ] <predicate> | [ ( ] <simple-predicate> [ ) ] }
[ { { AND | OR } [ NOT ] { <predicate> | [ ( ] <simple-predicate> [ ) ] }
[ ...n ]
]
```
```
<simple-predicate> ::=
{ expression <binary-operator> expression
| expression [ NOT ] EQUIV expression
| expression [ NOT ] IN
{ <scalar-query> | ( <value> ,...n ) }
| expression <inequality-operator>
{ ALL | ANY} { ( <scalar-query> ) | ( <value> ,...n ) }
| expression [ NOT ] BETWEEN expression [ AND ] expression
| [ NOT ] EXISTS { <column value> | <scalar-query> } }
```
When applied to a column `EXISTS` tests whether the returned `<row-type>` includes the required column. In the case of `<scalar-query>`, it tests whether a CTE returns any rows.
`[ NOT ] EQUIV` is a binary operator, similar to (not) equals `<>`, `=`. However, comparing two `NOT EXISTS` yields true.
`<scalar-query>` is a CTE that selects for one column. Depending on whether the operator expects a set or a value, it operates on the entire result set or on the first row returned, respectively. If the CTE is not ordered, results may be unpredictable.
```
<binary-operator> ::=
{ = | <> | != | > | >= | !> | < | <= | !< | EQUIV | NOT EQUIV}
```
Whitespace is not required between operands and binary-operators, except when the left operand is a numeric literal, in which case whitespace is required.
`<inequality-operator>` is any `<binary-operator>` other than equality and `EQUIV`.
```
<expression> ::=
{ <qualified-column>
| <constant>
| <scalar>
| <scalar-query>
| <aggregate-function>( { <column> | <scalar> } )
}
```
`<scalar-query>` is a CTE that returns only one column. The first returned value is accepted and subsequent values ignored. Ordering the CTE may be required for predictable results.
```
<column> ::=
{ <qualified-column>
| <column-alias>
| <constant> }
```
```
<qualified-column> ::=
[ [ <ship-qualifier> ]<table-view> | <alias> ].<column-name>
```
## API
```
+$ query
$:
%query
from=(unit from)
scalars=(list scalar-function)
predicate=(unit predicate)
group-by=(list grouping-column)
having=(unit predicate)
selection=select
order-by=(list ordering-column)
==
```
## Arguments
**`<table-set> [ [AS] <alias> ]`**
Any valid `<table-set>`.
`<alias>` allows short-hand reference to the `<table-set>` in the `SELECT` clause and subsequent `<predicates>`.
**`{ <qualified-column> | <column-alias> | <column-ordinal> }`**
Used to select columns for ordering and grouping. `<column-ordinal>`s are 1-based.
**`[ TOP <n> ] [ BOTTOM <n> ]`**
`SELECT` only the first and/or last `n` rows returned by the rest of the query. If the result set is less than `n`, the entire set of rows is returned.
`TOP` and `BOTTOM` require the presence of an `ORDER BY` clause.
## Remarks
The `SELECT` clause may choose columns from a single CTE, in which case the `FROM` clause is absent. It may also choose only constants and `SCALAR` functions on constants, in which case it returns a result set of one row.
The simplest possible query is `SELECT 0`.
`<query>` alone does not change the Obelisk agent state.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows returned.
## Exceptions
Provided `<query>` attempts execution (i.e., syntax and internal consistency checks pass), the only exceptions possible are performance-related, such as timeouts and memory constraints.

View File

@ -1,3 +1,5 @@
(currently supported in urQL parser, likely to be revised, may or may not be implemented in Obelisk)
# MERGE
`MERGE` is a statement that conditionally performs `INSERT`, `UPDATE`, or `DELETE` operations. It modifies the content of the `<target-table>`, merging data from the `<source-table>` and static `<common-table-expression>` sources.

View File

@ -1,3 +1,5 @@
(currently supported in urQL parser, likely to be revised, not yet supported in Obelisk)
# GRANT
Grants permission to read from and/or write to selected `<database>`, `<namespace>`, or `<table-object>` on host ship to selected foreign ships.

View File

@ -1,73 +1,3 @@
# CREATE INDEX
This command creates an index over selected column(s) of an existing table.
```
<create-index> ::=
CREATE [ UNIQUE ] [ LOOK-UP | CLUSTERED ] INDEX <index>
ON [ <db-qualifer> ] <table>
( <column> [ ASC | DESC ] [ ,...n ] )
```
## Examples
```
CREATE INDEX ix_vendor-id ON product-vendor (vendor-id);
CREATE UNIQUE INDEX ix_vendor-id2 ON dbo.product-vendor
(vendor-id DESC, name ASC, address DESC);
CREATE INDEX ix_vendor-id3 ON purchasing..product-vendor (vendor-id);
```
## API
```
+$ create-index
$:
%create-index
name=@t
object-name=qualified-object :: because index can be over table or view
is-unique=?
is-clustered=?
columns=(list ordered-column)
==
```
## Arguments
**`UNIQUE`**
Specifies that no two rows are permitted to have the same index key value.
**`LOOK-UP | CLUSTERED`**
`CLUSTERED` creates an index in which the logical order of the key values determines the physical order of the corresponding rows in a table. A `<table>` or `<view>` can have only one clustered index at a time.
**`<index>`**
User-defined name for the new index. This name must follow the Hoon term naming standard.
**`<table>`**
Name of existing table the index targets.
If not explicitly qualified, defaults to the Obelisk agent's current database and 'dbo' namespace.
**`<column> [ ASC | DESC ] [ ,...n ] `**
List of column names in the target table. This list represents the sort hierarchy and optionally specifies the sort direction for each level. The default sorting is `ASC` (ascending).
## Remarks
This command mutates the state of the Obelisk agent.
Index names cannot start with 'pk-' or 'fk-' as these prefixes are reserved for primary keys and foreign keys respectively.
_NOTE_: Further investigation is required to determine how "clustering" works in Hoon.
## Produced Metadata
## Example
INSERT `table name`, `namespace` `index-name`, `LOOK-UP | 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 PROCEDURE
Procedures are parameterized urQL scripts.

View File

@ -3,76 +3,10 @@
TBD
# DELETE
Deletes rows from a `<table-set>`.
```
<delete> ::=
DELETE [ FROM ] <table-set>
[ WHERE <predicate> ]
[ AS OF { NOW
| <timestamp>
| n { SECONDS | MINUTES | HOURS | DAYS | WEEKS | MONTHS | YEARS } AGO
| <inline-scalar>
}
]
```
## API
```
+$ delete
$:
%delete
table=qualified-object
predicate=(unit predicate)
==
```
## Arguments
**`<table-set>`**
The target of the `DELETE` operation.
**`<predicate>`**
Any valid `<predicate>`, including predicates on CTEs.
## Remarks
When `<table-set>` is a `<table>`, the command potentially mutates `<table>` resulting 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.
Data in the *sys* namespace cannot be deleted.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
## Produced Metadata
@@ROWCOUNT returns the total number of rows deleted
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
# INSERT
Inserts rows into a `<table-set>`.
```
<insert> ::=
INSERT INTO <table-set>
[ ( <column> [ ,...n ] ) ]
{ VALUES (<scalar-expression> [ ,...n ] ) [ ...n ]
| <transform> }
[ AS OF { NOW
| <timestamp>
| n { SECONDS | MINUTES | HOURS | DAYS | WEEKS | MONTHS | YEARS } AGO
| <inline-scalar>
}
]
```
```
<scalar-expression> ::=
{ <constant>
@ -81,171 +15,5 @@ Inserts rows into a `<table-set>`.
| [ unary-operator ] expression
| expression <binary-operator> expression }
```
Details of `<scalar-function>` are TBD. Refer to the Functions chapter currently under development.
## API
```
+$ insert
$:
%insert
table=qualified-object
columns=(unit (list @t))
values=insert-values
==
```
## Arguments
**`<table-set>`**
The target of the `INSERT` operation.
**`<column>` [ ,...n ]**
When present, the column list must account for all column identifiers (names or aliases) in the target once. It determines the order in which update values are applied and the output `<table-set>`'s column order.
**(`<scalar-expression>` [ ,...n ] ) [ ,...n ]**
Row(s) of literal values to insert into target. Source auras must match target columnwise.
**`<transform>`**
Transform creating source `<table-set>` to insert into target. Source auras must match target columnwise.
## Remarks
When `<table-set>` is a `<table>` the command potentially mutates `<table>`, resulting in a state change of the Obelisk agent.
When `INSERT` operates on a `<table>`, it must be in the terminal (last) step of a `<transform>` or a stand-alone `INSERT`.
Data in the *sys* namespace cannot be inserted into.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
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'`. Single quotes within cord values must be escaped with double backslash as `'this is a cor\\'d'`.
If `( <column> [ ,...n ] )` is not specified, the inserted columns must be arranged in the same order as the target `<table-set>`.
When the target `<table-set>` is a `<table>`, the 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.
Note that multiple parentheses enclosed rows of column values are NOT comma separated.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows inserted
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
unique key violation
colum misalignment
# TRUNCATE TABLE
Removes all rows in a base table.
```
<truncate-table> ::=
TRUNCATE TABLE [ <ship-qualifier> ] <table>
[ AS OF { NOW
| <timestamp>
| n { SECONDS | MINUTES | HOURS | DAYS | WEEKS | MONTHS | YEARS } AGO
| <inline-scalar>
}
]
```
## API
```
+$ truncate-table
$:
%truncate-table
table=qualified-object
==
```
## Arguments
**`<table>`**
The target table.
## Remarks
The command potentially mutates `<table>`, resulting in a state change of the Obelisk agent.
Tables in the *sys* namespace cannot be truncated.
## Produced Metadata
none
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
# UPDATE
Changes content of selected columns in existing rows of a `<table-set>`.
```
<update> ::=
UPDATE [ <ship-qualifier> ] <table-set>
SET { <column> = <scalar-expression> } [ ,...n ]
[ WHERE <predicate> ]
[ AS OF { NOW
| <timestamp>
| n { SECONDS | MINUTES | HOURS | DAYS | WEEKS | MONTHS | YEARS } AGO
| <inline-scalar>
}
]
```
## API
```
+$ update
$:
%update
table=qualified-object
columns=(list @t)
values=(list value-or-default)
predicate=(unit predicate)
==
```
## Arguments
**`<table-set>`**
The target of the `UPDATE` operation.
**`<column>` = `<scalar-expression>`**
`<column>` is a column name or alias of a target column. `<scalar-expression>` is a valid expression within the statement context.
**`<predicate>`**
Any valid `<predicate>`, including predicates on CTEs.
## Remarks
When `<table-set>` is a `<table>`, the command potentially mutates the data within `<table>`, resulting in a state change of the Obelisk agent.
A stand-alone `UPDATE` statement can only operate on a `<table>`, producing a `<transform>` of one command step with no CTEs.
Data in the *sys* namespace cannot be updated.
When `<table-set>` is a virtual table, the command produces an output `<table-set>` which may be consumed as a pass-thru by a subsequent `<transform>` step.
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'. Single quotes within cord values must be escaped with double backslash as `'this is a cor\\'d'`.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows updated
## Exceptions
`<table>` does not exist
`GRANT` permission on `<table>` violated
unique key violation
aura mismatch on `SET`

View File

@ -1,86 +1,11 @@
# QUERY
The `<query>` statement provides a means to create `<table-set>`s derived from persisted and/or cached `<table-set>`s and/or constants. Data rows can be joined based on predicates, specific columns can be selected, and the resulting rows can be filtered by predicate.
The full syntax involves complex manipulations at the row level through scalar functions, data aggregation across preliminary rows via aggregate functions, filtering by aggregation, and row ordering.
NOTE: scalar and aggregate functions are currently under development and not available. Also, these are subject to change.
```
<query> ::=
[ FROM <table-set> [ [AS] <alias> ]
{
{ JOIN | LEFT JOIN | RIGHT JOIN | OUTER JOIN }
<table-set> [ [AS] <alias> ]
ON <predicate>
} [ ...n ]
| CROSS JOIN <table-set> [ [AS] <alias> ]
]
[ { SCALAR <scalar> [ AS ] <scalar-function> } [ ...n ] ]
[ WHERE <predicate> ]
[ GROUP BY { <qualified-column>
| <column-alias>
| <column-ordinal> } [ ,...n ]
[ HAVING <predicate> ]
]
SELECT [ TOP <n> ] [ BOTTOM <n> ]
{ * | { [<ship-qualifier>]<table-view> | <alias> }.*
| <expression> [ [ AS ] <column-alias> ]
} [ ,...n ]
[ ORDER BY
{
{ <qualified-column> | <column-alias> | <column-ordinal> } { ASC | DESC }
} [ ,...n ]
]
```
`JOIN` is an inner join returning all matching pairs of rows.
`LEFT JOIN` is a left outer join returning all rows from the left table not meeting the join condition, along with all matching pairs of rows.
`RIGHT JOIN` is a right outer join returning all rows from the right table not meeting the join condition, along with all matching pairs of rows.
`OUTER JOIN` is a full outer join returning matching pairs of rows, as well as all rows from both tables not meeting the join condition.
`CROSS JOIN` is a cartesian join of two tables.
Cross database joins are permitted, but not cross ship joins.
`HAVING <predicate>` filters aggregated rows returned from the `<query>`. The column references in the predicate must be either one of the grouping columns or be contained in an aggregate function.
Avoid using `ORDER BY` in CTEs or in any query prior to the last step in a `<transform>`, unless required by `TOP` or `BOTTOM` specified in the `SELECT` statement or, in the case of CTEs, it is used in an `<expression>` expecting a scalar result.
```
<predicate> ::=
{ [ NOT ] <predicate> | [ ( ] <simple-predicate> [ ) ] }
[ { { AND | OR } [ NOT ] { <predicate> | [ ( ] <simple-predicate> [ ) ] }
[ ...n ]
]
```
```
<simple-predicate> ::=
{ expression <binary-operator> expression
| expression [ NOT ] EQUIV expression
| expression [ NOT ] IN
{ <scalar-query> | ( <value> ,...n ) }
| expression <inequality-operator>
{ ALL | ANY} { ( <scalar-query> ) | ( <value> ,...n ) }
| expression [ NOT ] BETWEEN expression [ AND ] expression
| [ NOT ] EXISTS { <column value> | <scalar-query> } }
```
When applied to a column `EXISTS` tests whether the returned `<row-type>` includes the required column. In the case of `<scalar-query>`, it tests whether a CTE returns any rows.
`[ NOT ] EQUIV` is a binary operator, similar to (not) equals `<>`, `=`. However, comparing two `NOT EXISTS` yields true.
`<scalar-query>` is a CTE that selects for one column. Depending on whether the operator expects a set or a value, it operates on the entire result set or on the first row returned, respectively. If the CTE is not ordered, results may be unpredictable.
```
<binary-operator> ::=
{ = | <> | != | > | >= | !> | < | <= | !< | EQUIV | NOT EQUIV}
```
Whitespace is not required between operands and binary-operators, except when the left operand is a numeric literal, in which case whitespace is required.
`<inequality-operator>` is any `<binary-operator>` other than equality and `EQUIV`.
```
<scalar-function> ::=
@ -106,76 +31,15 @@ See CH 8 Functions for full documentation on Scalars.
```
<expression> ::=
{ <qualified-column>
| <constant>
| <scalar>
| <scalar-query>
{ ...
| <aggregate-function>( { <column> | <scalar> } )
}
```
`<scalar-query>` is a CTE that returns only one column. The first returned value is accepted and subsequent values ignored. Ordering the CTE may be required for predictable results.
```
<aggregate-function> ::=
{ AVG | MAX | MIN | SUM | COUNT | AND | OR | <user-defined> }
```
```
<column> ::=
{ <qualified-column>
| <column-alias>
| <constant> }
```
```
<qualified-column> ::=
[ [ <ship-qualifier> ]<table-view> | <alias> ].<column-name>
```
## API
```
+$ query
$:
%query
from=(unit from)
scalars=(list scalar-function)
predicate=(unit predicate)
group-by=(list grouping-column)
having=(unit predicate)
selection=select
order-by=(list ordering-column)
==
```
## Arguments
**`<table-set> [ [AS] <alias> ]`**
Any valid `<table-set>`.
`<alias>` allows short-hand reference to the `<table-set>` in the `SELECT` clause and subsequent `<predicates>`.
**`{ <qualified-column> | <column-alias> | <column-ordinal> }`**
Used to select columns for ordering and grouping. `<column-ordinal>`s are 1-based.
**`[ TOP <n> ] [ BOTTOM <n> ]`**
`SELECT` only the first and/or last `n` rows returned by the rest of the query. If the result set is less than `n`, the entire set of rows is returned.
`TOP` and `BOTTOM` require the presence of an `ORDER BY` clause.
## Remarks
The `SELECT` clause may choose columns from a single CTE, in which case the `FROM` clause is absent. It may also choose only constants and `SCALAR` functions on constants, in which case it returns a result set of one row.
The simplest possible query is `SELECT 0`.
`<query>` alone does not change the Obelisk agent state.
## Produced Metadata
`@@ROWCOUNT` returns the total number of rows returned.
## Exceptions
Provided `<query>` attempts execution (i.e., syntax and internal consistency checks pass), the only exceptions possible are performance-related, such as timeouts and memory constraints.

View File

@ -1,64 +1,4 @@
# ALTER INDEX
Modifies the structure of an existing `<index>` on a user `<table>` or `<view>`.
```
<alter-index> ::=
ALTER [ UNIQUE ] [ NONCLUSTERED | CLUSTERED ] INDEX [ <db-qualifer> ]<index>
ON { <table> | <view> }
[ ( <column> [ ASC | DESC ] [ ,...n ] ) ]
{ DISABLE | RESUME}
```
## API
```
+$ alter-index
$:
%alter-index
name=qualified-object
object=qualified-object
columns=(list ordered-column)
action=index-action
==
```
## Arguments
**`UNIQUE`**
Specifies that no two rows are permitted to have the same index key value.
**`NONCLUSTERED | CLUSTERED`**
`CLUSTERED` creates an index in which the logical order of the key values determines the physical order of the corresponding rows in a table. A `<table>` or `<view>` can have only one clustered index at a time.
**`[ <db-qualifer> ]<index>`**
Specifies the target index.
**`<table> | <view>`**
Name of the underlying object of the index.
**`<column> [ ASC | DESC ] [ ,...n ] `**
List of column names in the target table. This list represents the sort hierarchy and optionally specifies the sort direction for each level. The default sorting is `ASC` (ascending).
**`DISABLE | RESUME`**
Used to disable an active index or resume a disabled index.
## Remarks
This command mutates the state of the Obelisk agent.
Cannot alter primary key and foreign key indices.
`RESUME` will rebuild the index if the underlying object is dirty.
Note: Further investigation into hoon ordered maps is needed to determine what exactly "clustered" means in hoon.
## Produced Metadata
update `<database>.sys.indices`
## Exceptions
index name does not exist for table
table does not exist
column does not exist
UNIQUE specified and existing values are not unique for the column(s) specified
# ALTER PROCEDURE

View File

@ -1,48 +1,3 @@
# DROP INDEX
Deletes an existing `<index>`.
```
<drop-index> ::=
DROP INDEX <index>
ON [ <db-qualifer> ] { <table> | <view> }
```
## API
```
+$ drop-index
$:
%drop-index
name=@tas
object=qualified-object
==
```
## Arguments
**`<index>`**
The name of the index to delete.
**`<table> | <view>`**
`<table>` or `<view>` with the named index.
## Remarks
This command mutates the state of the Obelisk agent.
Indexes with names that begin with "pk-" cannot be dropped, as these are table primary keys.
This command can be used to delete a `<foreign-key>`.
If `<view>` is shadowing `<table>`, the system attempts to find `<index>` on `<view>` first, then `<table>`.
## Produced Metadata
DELETE FROM `<database>.sys.indices`
DELETE FROM `<database>.sys.table-ref-integrity`
## Exceptions
`<table>` or `<view>` does not exist
`<index>` does not exist on `<table>` or `<view>`.
# DROP TRIGGER