DorisStore — Apache Doris real-time OLAP store
Read this page in the documentation
DorisStore — Apache Doris real-time OLAP store Overview Apache Doris is a real-time MPP analytical (OLAP) database. Like StarRocks (with which it shares ancestry), it speaks the MySQL wire protocol, so it is queried with the mysql2 driver over a normal MySQL connection/pool. Doris is a columnar analytics engine rather than an OLTP store, which does not fit this ORM's SQL Dialect abstraction cleanly, so it is modelled as a NoSqlStore (src/nosql/store.ts) exposing a direct query/ingest surface. Identity: Property | Value | --------- | ---------- | name | 'doris' | library | 'mysql2' | Driver: mysql2 (MySQL-wire), lazy-loaded The mysql2 package is an optional peer dependency. It is lazily required (require('mysql2/promise')) inside connect(), so importing this module never forces it to be installed — it is only needed when the store actually connects and builds a real connection. Injected client DorisStoreOptions accepts a pre-built client — a mysql2 connection/pool (or a compatible mock) implementing the small MysqlConnectionLike shape. When provided, connect() uses it directly and skips require('mysql2/promise') entirely. This is how the test suite injects a mock without the real driver installed. Ingestion note ingest() performs a batched INSERT over the MySQL wire. For high-throughput loading Doris also offers Stream Load (an HTTP PUT /api/{db}/{table}/streamload endpoint); that is a separate transport and is intentionally not wired here. Connection Build a store from connection options and call connect(): Connection options (all optional; the discrete fields map onto mysql2 connection config): Option | Type | Purpose | ------------------- | -------------------------- | --------------------------------------------------------------- | host | string | Doris frontend host. | port | number | MySQL-protocol query port (Doris frontend). | user | string | User name. | password | string | Password. | database | string | Default database. | connectionOptions | Record<string, unknown> | Any other mysql2 connection option, spread into the config. | client | MysqlConnectionLike | Pre-built connection/pool (or mock). When set, require('mysql2/promise') is skipped. | Injected-client form Methods Failures from the driver are wrapped in a DatabaseError (via DatabaseError.from, message prefixed Doris query failed: / Doris ingest failed:, and carrying the offending sql). Using query/ingest/getClient before connect() (or after disconnect()) throws a ConnectionError. Lifecycle Method | Signature | Behavior | ------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------- | connect | connect(): Promise<void> | Uses an injected client, otherwise lazy-requires mysql2/promise and createConnection(...). Idempotent. Failures wrapped in ConnectionError. | disconnect | disconnect(): Promise<void> | Calls the connection's optional end() and clears state. | isConnected | isConnected(): boolean | true only when connected and a client is present. | getClient | getClient(): MysqlConnectionLike | Returns the underlying mysql2 connection. Throws ConnectionError if not connected. | Query + ingest Method | Signature | Behavior | -------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | query | query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<T[]> | Executes SQL over the MySQL wire with optional positional params, returning the rows (the first element of mysql2's [rows, fields] tuple). | ingest | ingest(table: string, rows: Array<Record<string, unknown>>): Promise<any> | Batch-inserts rows into table via a single parameterized INSERT INTO table (cols) VALUES ? (columns taken from the first row; mysql2 expands the nested array into a bulk VALUES list). Returns the driver result (OkPacket). Throws DatabaseError for empty rows or empty columns. | Example Verification status Unit / mock-verified only. The tests in tests/nosql/doris.test.ts are fully mock-driven: mysql2 is not installed, so every test injects a mock connection (a query() spy returning mysql2's [rows, fields] tuple) via DorisStoreOptions.client, which makes connect() skip require('mysql2/promise'). There is no network and no live Doris server. What this proves: query() forwards sql + params to the driver and returns the rows tuple element. ingest() builds INSERT INTO events (a, b) VALUES ? and passes the correctly nested value arrays, returning the driver result. ingest() throws for an empty rows array. Lifecycle: connecting via an injected client, idempotent connect(), disconnect() calling client.end(), and ConnectionError before connect() (from both getClient() and query()). Error handling: a failing query() wrapped in DatabaseError. What this does not prove: live execution against a real Doris frontend over the MySQL wire. Statement/parameter shapes are asserted against mysql2's documented contract, but end-to-end execution has not been exercised here. Related reading All data stores — the full catalogue, grouped by purpose Database types — where this sits among the 22 categories