Interface JdbcDialect


public interface JdbcDialect
The SQL of one database product (06-stores.md §2.1), replacing the custom SQL settings of 4.x. The built-in dialects are 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):

  • Method Summary

    Modifier and Type
    Method
    Description
    default String
    addColumn(String table, String column, String definition)
    The statement that adds a column to an existing table, for options.initSchema on tables created by an earlier 5.0 pre-release (cosid_namespace.slot_offset came after 5.0.0-alpha.1).
    default void
    checkKey(String what, String key)
    Rejects a key the database could not keep apart from another one.
    default String
    createIndex(String table, String name, List<String> columns)
    The statement that creates an index, for options.initSchema on a table that lacks it (cosid_slot's index on (namespace, last_owner_key) came after 5.0.0-alpha.1).
    default String
    firstRows(String columns, String table, String where, String orderBy, int rows)
    Selects the first rows rows of orderBy that match where, without locking them (limit; SQL Server top).
    default boolean
    insertNamespaceIfAbsent(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 boolean
    Whether a failure is a duplicate key, as two concurrent inserts of one key give.
    default boolean
    Whether a failed statement may simply run again: a deadlock victim or a serialization failure.
    default boolean
    Whether a failure is the statement running out of the query timeout (StoreConfig.timeout); the store then fails with StoreTimeoutException.
    The dialect name, for options.dialect and messages.
    The store clock as an SQL expression: UTC epoch milliseconds as a bigint, unaffected by the session time zone and daylight saving time.
    void
    provisionSlots(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)
    Reserves size values of key in one round trip where the database allows it: a key that does not exist is created with next_value = initialOffset + size; an existing key that is not sealed and has next_value <= Long.MAX_VALUE - size gets next_value + size.
    The statements that create the tables when they do not exist (options.initSchema); each is idempotent.
    default String
    A query of one row and one column, the store clock (nowMillis()): what a renewal reads before its compare-and-set.
    boolean
    Whether this dialect is the one of a database.
  • Method Details

    • name

      String name()
      The dialect name, for options.dialect and messages.
      Returns:
      the name, such as mysql
    • supports

      boolean supports(DatabaseMetaData metaData) throws SQLException
      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

      List<String> schema(JdbcTables tables)
      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 a bigint, unaffected by the session time zone and daylight saving time.
      Returns:
      the expression
    • selectNowMillis

      default String selectNowMillis()
      A query of one row and one column, the store clock (nowMillis()): what a renewal reads before its compare-and-set.
      Returns:
      select and 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
      Reserves size values of key in one round trip where the database allows it: a key that does not exist is created with next_value = initialOffset + size; an existing key that is not sealed and has next_value <= Long.MAX_VALUE - size gets next_value + size. The caller guarantees initialOffset <= Long.MAX_VALUE - size.
      Parameters:
      session - the session
      key - the range key
      size - the size, positive
      initialOffset - where a new key starts
      Returns:
      the new next_value; empty if the key is sealed or the range would pass Long.MAX_VALUE
      Throws:
      SQLException - if the database fails; a duplicate key of two concurrent first reserves is retried
    • firstRows

      default String firstRows(String columns, String table, String where, String orderBy, int rows)
      Selects the first rows rows of orderBy that match where, without locking them (limit; SQL Server top). The statement must be usable as a derived table.
      Parameters:
      columns - the selected columns
      table - the table
      where - the condition
      orderBy - the order
      rows - how many rows at most
      Returns:
      the select statement
    • createIndex

      default String createIndex(String table, String name, List<String> columns)
      The statement that creates an index, for options.initSchema on 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, as JdbcTables names it
      name - the index name, unqualified
      columns - the indexed columns, in order
      Returns:
      the statement
    • addColumn

      default String addColumn(String table, String column, String definition)
      The statement that adds a column to an existing table, for options.initSchema on tables created by an earlier 5.0 pre-release (cosid_namespace.slot_offset came after 5.0.0-alpha.1). The store runs it only when the column is missing.
      Parameters:
      table - the table, as JdbcTables names it
      column - the column
      definition - its type, nullability and default, such as integer 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 leaves slot_offset out, so that it also runs on a table of 5.0.0-alpha.1 that has no such column.
      Parameters:
      session - the session
      namespace - the namespace
      limit - the slot limit
      toleranceMillis - the tolerance
      slotOffset - 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

      void provisionSlots(JdbcSession session, String namespace, int limit) throws SQLException
      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 session
      namespace - the namespace
      limit - the slot limit
      Throws:
      SQLException - if the database fails; a duplicate key of concurrent provisioning is retried by the caller
    • checkKey

      default void checkKey(String what, String key)
      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 key
      key - the key
      Throws:
      IllegalArgumentException - if the database cannot store the key apart from its neighbours
    • isDuplicateKey

      default boolean isDuplicateKey(SQLException e)
      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

      default boolean isRetryable(SQLException e)
      Whether a failed statement may simply run again: a deadlock victim or a serialization failure.
      Parameters:
      e - the failure
      Returns:
      true for SQL states 40001 and 40P01
    • isTimeout

      default boolean isTimeout(SQLException e)
      Whether a failure is the statement running out of the query timeout (StoreConfig.timeout); the store then fails with StoreTimeoutException.
      Parameters:
      e - the failure
      Returns:
      true for a SQLTimeoutException and the SQL states 57014 (query canceled: PostgreSQL, H2) and HY008 (operation canceled: SQL Server)