Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SQL databases

Postgres, MySQL, SQL Server, StarRocks and Doris are read with a SQL query and written by bulk load or insert; their options are listed under Connections. What is particular to each follows.

StarRocks

A starrocks connection is both ends: LOAD INTO sr.t writes by stream load (be_url), and FROM sr.db.t / sr.QUERY($$...$$) reads through the FE’s MySQL protocol (fe_host/host, fe_port/port, default 9030) with the same user/password — no second mysql connection pointed at the FE is needed. Reads get everything a SQL source gets: WHERE and whole-aggregate pushdown in the StarRocks dialect, key-range splits under -j, and FOR EACH ROW OF (sr.QUERY(...)) discovery.

Before a load, the target’s database and table are created only if information_schema does not list them (auto_create = false skips this altogether). A role allowed to load into an existing table therefore needs no CREATE privilege; one that does lack a privilege it needs gets StarRocks’ own message in the error (starrocks refused 'CREATE TABLE …': Access denied; you need …), not only in the log.

Doris

A doris connection is the same in every respect — Doris is the project StarRocks forked from, read through its FE and loaded by stream load — except for the tables it creates. Doris takes no FLOAT, DOUBLE or STRING column as a key, so an APPEND or REPLACE target is a duplicate table with no sort key (DISTRIBUTED BY RANDOM), where StarRocks keys on the first column; an UPSERT ON (k) target is a UNIQUE KEY table with merge-on-write, its text keys VARCHAR(65533), and PARTIAL COLS loads as Doris’ partial_columns. Timestamps are DATETIME(6), to keep microseconds. Loads run in Doris’ strict mode, so a value that does not convert fails the load instead of landing as NULL.

SQL Server

Named SQL Server instances: write host = 'sql01.corp.local\SALES'. When a host carries a \INSTANCE and no explicit port is given, basalt resolves the instance’s TCP port via the SQL Server Browser (UDP 1434) before connecting. Give an explicit port to skip the lookup — the robust choice where UDP 1434 is firewalled but the TDS port is open. (*.dynamics.com / Azure SQL are default-instance cloud endpoints, so this never applies there.)

Windows authentication (auth = 'ntlm' or 'kerberos'): authenticates to an on-prem SQL Server with a domain account. Give the domain either inline — user = 'CORP\myuser' — or as its own option, domain = 'CORP'; when both appear the domain option wins and the CORP\ prefix is stripped off the user name. Either way it is a login with an explicit password, not single sign-on from the host’s logged-in identity: basalt runs on Linux, holds no system ticket, reads no keytab, and always needs password.

auth = 'kerberos' is for a server or domain that refuses NTLM. It needs the realm — realm = 'CORP.LOCAL', the domain’s DNS name, or a user written myuser@CORP.LOCAL — and asks the KDC for a ticket to MSSQLSvc/<host>:<port> with the resolved port (a named instance’s included), so host is the server’s DNS name as registered in AD; when it is not (an IP, an alias), spn names the service: spn = 'MSSQLSvc/sql01.corp.local:1433'. The KDC is kdc = 'host[:port]', else the one DNS lists for _kerberos._tcp.<realm>, else the realm’s own name; AES keys only, RC4 refused, tickets reused until they expire. The server’s reply must prove it holds the service’s key, or the login is refused. The channel is always TLS (tls = 'off' is taken as 'require'). Extended Protection set to Required on the server is not supported.

Encryption is mandatory for auth = 'ntlm': tls = 'off' is a plan-time error, refused before any socket opens, because an unencrypted NTLM exchange hands the challenge/response to any passive observer for offline cracking. tls = 'require' verifies the server certificate and is the right setting; tls = 'insecure' encrypts without verifying and is accepted, since on-prem instances usually present a self-signed certificate — but an unverified channel still leaves an active man-in-the-middle able to relay the handshake. Point BASALT_CA_BUNDLE at the PEM of your internal CA and use tls = 'require' to close that gap. Note that NTLMv2 never puts the password on the wire — only a challenge-response derived from it — whereas a SQL login sends it under LOGIN7’s trivially reversible scrambling, so on an unverified channel NTLM is the stronger of the two, not the weaker.