Skip to main content

Doris catalog

The Doris catalog connects Gravitino to an Apache Doris cluster over the MySQL protocol, exposing Doris databases as schemas and Doris tables as tables. Schemas and tables are both read-write. One catalog reaches every database on the frontend named in jdbc-url.

Gravitino records its own identifier in the comment of each schema and table it creates, as text of the form (From Gravitino, DO NOT EDIT: gravitino.v1.uid{id}), and uses it to recognize the object on later loads. Leave that text in place when you edit a comment in Doris directly.

Quick start​

The example connects a Doris frontend as the catalog doris_sales and lists its databases as schemas. The catalog uses MySQL Connector/J, which does not ship in the image. Enable it with gravitino.jdbcDrivers.mysql before you start, as described in JDBC driver.

my-values.yaml
gravitino:
jdbcDrivers:
enabled: true
mysql:
enabled: true
  1. Start the catalog. Open Connect → Catalogs and click + Catalog. Enter doris_sales as the Catalog name, keep Relational as the Catalog type, and choose Apache Doris under Databases and warehouses in Select provider.

  2. Enter the connection. Under Connection, enter jdbc:mysql://{doris_fe_host}:9030 as the URL, and the User and Password Gravitino connects as. Advanced holds Cloud / region and a Properties list for any other catalog property. The UI fills in jdbc-driver itself.

  3. Test and create it. Click Test connection, then Create catalog.

  4. List the schemas. In Explore, open doris_sales. The schemas listed are the Doris databases, read from the frontend.

Catalog properties​

The Doris catalog defines no catalog properties of its own; it takes the connection, pool, and driver properties every JDBC catalog shares, listed in Shared properties.

jdbc-url points at a frontend's MySQL protocol port, and jdbc-driver is com.mysql.cj.jdbc.Driver.

Driver version compatibility​

The catalog checks the Connector/J version it finds. The chart's default Connector/J, 8.0.33, meets both rules below.

Connector/J versionEffect
Below 8.0Catalog creation fails, naming the driver version found
8.0.0 to 8.0.15The precision of a plain DATETIME column is unknown; it loads without precision and a warning is logged
8.0.16 and laterFull support

The 8.0.16 boundary matters only for columns Doris reports as plain DATETIME. A column reported as DATETIME(p) takes its precision from the type string with any driver version.

Schemas​

A schema in this catalog is a Doris database. Create, list, load, and drop are supported; alter is not. Listing filters out information_schema.

Doris has no schema comment syntax, so Gravitino writes the comment as a database property named comment and reads it back from SHOW CREATE DATABASE. Any other schema property is written to the PROPERTIES clause of CREATE DATABASE and read back the same way.

Dropping a schema that still holds tables fails unless the drop cascades.

warning

A cascading drop issues DROP DATABASE ... FORCE. Doris does not keep a database dropped with FORCE in its recycle bin, so the database and every table in it cannot be recovered with RECOVER.

Tables​

Table create, load, list, rename, alter, and drop are supported. Purge is not, and a purge request is rejected rather than being treated as a drop. A drop issues DROP TABLE without FORCE.

Every Doris table needs a distribution, so a create without one is rejected. See Partitioning and distribution.

After creating a table, Gravitino reads its comment back from information_schema and rewrites it with ALTER TABLE ... MODIFY COMMENT if Doris did not store it, since some Doris planners discard a table comment at create time. The connecting user needs ALTER privilege only when that repair runs.

Doris applies column changes as an asynchronous schema change job. A load issued immediately after an alter can return the schema from before the change.

Properties​

Two table properties are declared by the catalog. Any other property is passed to the PROPERTIES clause of CREATE TABLE, and Doris decides whether it accepts it. Properties are read back from SHOW CREATE TABLE.

PropertyDescriptionDefault
replication_numThe number of replicas for the table1 when fewer than three backends are alive, otherwise the Doris default
replication_allocationThe replica allocation policy for the tableNone

The two properties cannot be set together. When neither is set, Gravitino runs SHOW BACKENDS to count the live backends, so the connecting user needs permission to run it; a create fails if the count cannot be read.

A set property is issued as ALTER TABLE ... SET (...), and several set properties in one request share that clause. Removing a property is rejected.

Indexes​

Each index other than a unique key covers exactly one top-level column.

Gravitino index typeDoris DDLRead back as
PRIMARY_KEYINDEX `{name}` (`{column}`), no USINGPRIMARY_KEY when named PRIMARY
UNIQUE_KEYUNIQUE KEY({columns}), the table model keyUNIQUE_KEY
INVERTEDINDEX `{name}` (`{column}`) USING INVERTEDINVERTED
BITMAPINDEX `{name}` (`{column}`), no USINGINVERTED
VECTORINDEX `{name}` (`{column}`) USING ANNVECTOR

A table takes at most one UNIQUE_KEY. It is emitted as the table model key rather than in the index clause, and Doris requires its columns to lead the column list. A table with no unique key is created with the Doris duplicate key model.

BITMAP is written without a USING clause for older Doris releases and is read back as INVERTED, so a bitmap index does not round-trip under its own type. Doris bloom filter indexes are read back as DATA_SKIPPING_BLOOM_FILTER but cannot be created through Gravitino, and an index type Gravitino does not recognize is read back as INVERTED.

An alter can add INVERTED, BITMAP, and VECTOR indexes and can delete any index. Primary and unique keys cannot be added after creation.

Define a unique key and an inverted index
{
"indexes": [
{"indexType": "UNIQUE_KEY", "name": "uk_id", "fieldNames": [["id"]]},
{"indexType": "INVERTED", "name": "idx_name", "fieldNames": [["name"]]}
]
}

Partitioning and distribution​

A table takes at most one partitioning transform, either range on one column or list on one or more columns. Composite partitioning and nested fields are rejected, and every partition column must be a column of the table. Partitions can be pre-assigned in the create request, and after creation they are listed, added, and dropped through the partitions API.

The distribution is required and must be hash or even.

Gravitino distributionDoris clauseNotes
hashDISTRIBUTED BY HASH({columns})Every column must exist in the table
evenDISTRIBUTED BY RANDOMTakes no columns

The bucket number controls the BUCKETS clause. 0 omits it, so Doris applies its default, and -1 writes BUCKETS AUTO, which needs Doris 1.2.2 or later.

Hash distribution with automatic buckets
{
"distribution": {
"strategy": "hash",
"number": -1,
"funcArgs": [{"type": "field", "fieldName": ["id"]}]
}
}

Sort orders are not supported.

Auto increment​

An auto-increment column is written as AUTO_INCREMENT and needs Doris 2.1.0 or later. Gravitino reads the version from SHOW FRONTENDS when the create carries an auto-increment column, so the connecting user needs permission to run it.

A table can have only one auto-increment column, and it must be covered by a PRIMARY_KEY or UNIQUE_KEY index. Doris adds its own rules: the column must be BIGINT NOT NULL with no default.

Define an auto-increment unique key
{
"columns": [
{"name": "id", "type": "long", "nullable": false, "autoIncrement": true}
],
"indexes": [
{"indexType": "UNIQUE_KEY", "name": "uk_id", "fieldNames": [["id"]]}
]
}

Supported changes​

All changes in one request other than a rename are issued as a single ALTER TABLE statement.

ChangeSupported
Rename tableYes, alone in its request
Update table commentYes
Add columnYes, at any position; a default value is not applied
Delete columnYes
Rename columnNo
Update column typeYes; the column's default is removed
Update column positionYes
Update column commentYes
Update column nullableYes, except to NOT NULL on a column whose default is null
Update column defaultNo
Update column auto incrementNo
Add indexYes, for INVERTED, BITMAP, and VECTOR
Delete indexYes
Set propertyYes
Remove propertyNo

Nested column names are rejected by every column change.

Identifier case and quoting​

Names are case-sensitive in Gravitino and are passed to Doris exactly as given, never folded. Schema, table, and column names must match ^\w[\w/=-]{0,63}$: 1 to 64 characters, starting with an ASCII letter, digit, or underscore, and continuing with those or /, =, and -. Doris applies its own naming rules on top.

Gravitino quotes identifiers with backticks in generated SQL. Names returned by a list operation come back exactly as Doris stores them.

Type mapping​

Gravitino reads each Doris type as the Gravitino type in its row, and creates each Gravitino type as the Doris type in its row, except where the list under the table says otherwise.

Doris typeGravitino type
BOOLEANBoolean
TINYINTByte
SMALLINTShort
INTInteger
BIGINTLong
FLOATFloat
DOUBLEDouble
DECIMAL(p,s)Decimal(p, s)
DATE, DATEV2Date
DATETIME(p)Timestamp without time zone, precision p
DATETIMETimestamp without time zone
CHAR(n)Char(n)
VARCHAR(n)Varchar(n)
STRING, TEXTString
BINARY, VARBINARYBinary
JSON, VARIANT, IPV4, IPV6, LARGEINT, BITMAP, HLLExternal type carrying the Doris type string
ARRAY, MAP, STRUCT, and any other typeExternal type carrying the Doris type string

An external type keeps the full type string in lowercase, such as array<int(11)>, so composite types are not resolved into Gravitino list, map, or struct types.

When Gravitino creates a column:

  • Date becomes datev2.
  • Timestamp without time zone becomes datetime(p), or datetime when no precision is set.
  • Varchar(n) takes n from 1 to 65533, and Char(n) takes n from 1 to 255.
  • Binary becomes binary.
  • An external type becomes the Doris type string it carries.
  • Any other Gravitino type is rejected, including Fixed, UUID, Time, timestamp with time zone, the interval types, and list, map, struct, and union types.

Column default values​

CURRENT_TIMESTAMP is recognized as the current timestamp default in both directions. Literal defaults on numeric, decimal, date, datetime, char, varchar, and text columns are parsed into typed literals. Any other default, and any expression, is preserved as an unparsed expression. A function default other than CURRENT_TIMESTAMP is written inside parentheses.

Error mapping​

Doris error codes are translated into Gravitino exceptions so a caller sees the same failure types it would from any other catalog. Doris often reports a failure as the generic code 1105 with the detail in the message; Gravitino then derives the code from the message text.

Doris errorGravitino exception
1007 database existsSchema already exists
1050 table already existsTable already exists
1008, 1049 database does not existNo such schema
1051, 1109 unknown tableNo such table
1045 access denied for userUnauthorized
1054 unknown columnNo such column
1507 partition does not existNo such partition
1517 duplicate partition namePartition already exists
1064 syntax error at AUTORuntime error explaining that BUCKETS AUTO needs Doris 1.2.2 or later
Any other code with "Access denied" in the messageConnection failed

Any other error produces a generic runtime exception carrying the Doris message.