Interface JdbcDialect
JdbcDialects; another one is registered with ServiceLoader under this
interface, is detected before the built-in ones, and can be named by options.dialect.
The store runs everything else itself: the slot choice of 05 §2.1 as one read of the candidates
(firstRows(java.lang.String, java.lang.String, java.lang.String, java.lang.String, int)) and compare-and-set updates, renewals and releases as compare-and-set updates, all stamped by
nowMillis(). The
tables are those of schema(me.ahoo.cosid.store.jdbc.JdbcTables): cosid_range(range_key, next_value, sealed),
cosid_slot(namespace, slot, owner_key, incarnation, last_owner_key, fence, expires_at, floor_ms, ceiling_ms,
next_floor_ms) and cosid_namespace(namespace, slot_limit, tolerance_ms, slot_offset), under the names of
JdbcSession.tables(). Tables of 5.0.0-alpha.1 have no cosid_namespace.slot_offset: a missing value
reads as 0, and options.initSchema adds the column (addColumn(java.lang.String, java.lang.String, java.lang.String)).
Two kinds of method, with different promises (R1-jdbc-07):
- The operations (
reserve(me.ahoo.cosid.store.jdbc.JdbcSession, java.lang.String, long, long),insertNamespaceIfAbsent(me.ahoo.cosid.store.jdbc.JdbcSession, java.lang.String, int, long, int),provisionSlots(me.ahoo.cosid.store.jdbc.JdbcSession, java.lang.String, int),nowMillis(),schema(me.ahoo.cosid.store.jdbc.JdbcTables),checkKey(java.lang.String, java.lang.String)and the error classification) are the contract a dialect implements: their meaning does not change in 5.x. - The SQL hooks (
firstRows(java.lang.String, java.lang.String, java.lang.String, java.lang.String, int),createIndex(java.lang.String, java.lang.String, java.util.List<java.lang.String>),addColumn(java.lang.String, java.lang.String, java.lang.String),selectNowMillis()) only spell a piece of SQL the store builds its own statements from. The store may stop calling one or start calling a new one in a minor version; a new hook always has a default that suits most databases. Override a hook only where the database's syntax differs.
-
Method Summary
Modifier and TypeMethodDescriptiondefault StringThe statement that adds a column to an existing table, foroptions.initSchemaon tables created by an earlier 5.0 pre-release (cosid_namespace.slot_offsetcame after 5.0.0-alpha.1).default voidRejects a key the database could not keep apart from another one.default StringcreateIndex(String table, String name, List<String> columns) The statement that creates an index, foroptions.initSchemaon a table that lacks it (cosid_slot's index on(namespace, last_owner_key)came after 5.0.0-alpha.1).default StringSelects the firstrowsrows oforderBythat matchwhere, without locking them (limit; SQL Servertop).default booleaninsertNamespaceIfAbsent(JdbcSession session, String namespace, int limit, long toleranceMillis, int slotOffset) Records the parameters of a namespace on its first use; a namespace that exists is left as it is.default booleanWhether a failure is a duplicate key, as two concurrent inserts of one key give.default booleanWhether a failed statement may simply run again: a deadlock victim or a serialization failure.default booleanWhether a failure is the statement running out of the query timeout (StoreConfig.timeout); the store then fails withStoreTimeoutException.name()The dialect name, foroptions.dialectand messages.The store clock as an SQL expression: UTC epoch milliseconds as abigint, unaffected by the session time zone and daylight saving time.voidprovisionSlots(JdbcSession session, String namespace, int limit) Creates the rows of slots[0, limit)of a namespace that do not exist yet, with the column defaults; existing rows are left as they are.reserve(JdbcSession session, String key, long size, long initialOffset) Reservessizevalues ofkeyin one round trip where the database allows it: a key that does not exist is created withnext_value = initialOffset + size; an existing key that is not sealed and hasnext_value <= Long.MAX_VALUE - sizegetsnext_value + size.schema(JdbcTables tables) The statements that create the tables when they do not exist (options.initSchema); each is idempotent.default StringA query of one row and one column, the store clock (nowMillis()): what a renewal reads before its compare-and-set.booleansupports(DatabaseMetaData metaData) Whether this dialect is the one of a database.
-
Method Details
-
name
String name()The dialect name, foroptions.dialectand messages.- Returns:
- the name, such as
mysql
-
supports
Whether this dialect is the one of a database.- Parameters:
metaData- the metadata of a connection to it- Returns:
- true if this dialect handles the database
- Throws:
SQLException- if the metadata cannot be read
-
schema
The statements that create the tables when they do not exist (options.initSchema); each is idempotent.- Parameters:
tables- the table names- Returns:
- the statements, in order
-
nowMillis
String nowMillis()The store clock as an SQL expression: UTC epoch milliseconds as abigint, unaffected by the session time zone and daylight saving time.- Returns:
- the expression
-
selectNowMillis
A query of one row and one column, the store clock (nowMillis()): what a renewal reads before its compare-and-set.- Returns:
selectand the clock, without a table; a database that needs one overrides it (Oracle:from dual)
-
reserve
OptionalLong reserve(JdbcSession session, String key, long size, long initialOffset) throws SQLException Reservessizevalues ofkeyin one round trip where the database allows it: a key that does not exist is created withnext_value = initialOffset + size; an existing key that is not sealed and hasnext_value <= Long.MAX_VALUE - sizegetsnext_value + size. The caller guaranteesinitialOffset <= Long.MAX_VALUE - size.- Parameters:
session- the sessionkey- the range keysize- the size, positiveinitialOffset- where a new key starts- Returns:
- the new
next_value; empty if the key is sealed or the range would passLong.MAX_VALUE - Throws:
SQLException- if the database fails; a duplicate key of two concurrent first reserves is retried
-
firstRows
Selects the firstrowsrows oforderBythat matchwhere, without locking them (limit; SQL Servertop). The statement must be usable as a derived table.- Parameters:
columns- the selected columnstable- the tablewhere- the conditionorderBy- the orderrows- how many rows at most- Returns:
- the select statement
-
createIndex
The statement that creates an index, foroptions.initSchemaon a table that lacks it (cosid_slot's index on(namespace, last_owner_key)came after 5.0.0-alpha.1). The store runs it only when the index is missing.- Parameters:
table- the table, asJdbcTablesnames itname- the index name, unqualifiedcolumns- the indexed columns, in order- Returns:
- the statement
-
addColumn
The statement that adds a column to an existing table, foroptions.initSchemaon tables created by an earlier 5.0 pre-release (cosid_namespace.slot_offsetcame after 5.0.0-alpha.1). The store runs it only when the column is missing.- Parameters:
table- the table, asJdbcTablesnames itcolumn- the columndefinition- its type, nullability and default, such asinteger not null default 0- Returns:
- the statement:
alter table <table> add column <column> <definition>by default
-
insertNamespaceIfAbsent
default boolean insertNamespaceIfAbsent(JdbcSession session, String namespace, int limit, long toleranceMillis, int slotOffset) throws SQLException Records the parameters of a namespace on its first use; a namespace that exists is left as it is. A slot offset of 0 is the column default: the statement then leavesslot_offsetout, so that it also runs on a table of 5.0.0-alpha.1 that has no such column.- Parameters:
session- the sessionnamespace- the namespacelimit- the slot limittoleranceMillis- the toleranceslotOffset- the slot offset, not negative- Returns:
- whether this call inserted the row: the one first use that creates the slot rows
- Throws:
SQLException- if the database fails; a duplicate key counts as "not inserted"
-
provisionSlots
Creates the rows of slots[0, limit)of a namespace that do not exist yet, with the column defaults; existing rows are left as they are.- Parameters:
session- the sessionnamespace- the namespacelimit- the slot limit- Throws:
SQLException- if the database fails; a duplicate key of concurrent provisioning is retried by the caller
-
checkKey
Rejects a key the database could not keep apart from another one. Keys are exact on every built-in dialect (binary collations, 06 §2.1), except that SQL Server ignores trailing spaces when it compares strings, whatever the collation: there a key ending with a space would silently share the row of the key without it.- Parameters:
what- what the key is, for the message:range key,namespace,owner keykey- the key- Throws:
IllegalArgumentException- if the database cannot store the key apart from its neighbours
-
isDuplicateKey
Whether a failure is a duplicate key, as two concurrent inserts of one key give.- Parameters:
e- the failure- Returns:
- true for SQL state class
23
-
isRetryable
Whether a failed statement may simply run again: a deadlock victim or a serialization failure.- Parameters:
e- the failure- Returns:
- true for SQL states
40001and40P01
-
isTimeout
Whether a failure is the statement running out of the query timeout (StoreConfig.timeout); the store then fails withStoreTimeoutException.- Parameters:
e- the failure- Returns:
- true for a
SQLTimeoutExceptionand the SQL states57014(query canceled: PostgreSQL, H2) andHY008(operation canceled: SQL Server)
-