Commit b36dcaa
committed
feat: temporal functions + 2PC durable log + connection timeouts
Adds the two biggest gaps from the codebase review: temporal functions
(NOW, EXTRACT equivalents, epoch conversion, DATEDIFF) and 2PC crash
recovery via a write-ahead log. Also adds client-level read/write
timeouts to all backend connections so a wedged backend can no longer
hang the coordinator forever.
1094/1131 tests pass, 0 failures, 37 skipped (require Docker).
+37 new tests (21 datetime, 11 WAL, 3 timeout, 2 misc).
----- Temporal functions -----
Zero temporal functions were previously registered. Any query referring
to NOW(), CURRENT_DATE, YEAR(col), MONTH(col), UNIX_TIMESTAMP(), etc.
failed -- a huge gap since a large fraction of real analytical queries
use at least one of these. Registered for both MySQL and PostgreSQL
dialects:
- NOW, CURRENT_TIMESTAMP -> DATETIME (current wall time)
- CURRENT_DATE, CURDATE -> DATE
- CURRENT_TIME, CURTIME -> TIME
- YEAR, MONTH, DAY, DAYOFMONTH -> INT64 component extractors
- HOUR, MINUTE, SECOND -> INT64 component extractors
- UNIX_TIMESTAMP (0 or 1 arg) -> INT64 seconds since epoch
- FROM_UNIXTIME (1 arg) -> DATETIME
- DATEDIFF (2 args) -> INT64 days between dates
All extractors accept DATE, DATETIME, TIMESTAMP, or a parseable string
on input; all return NULL for NULL inputs or unparseable strings.
DATEDIFF uses floor division so negative differences round correctly
across the day boundary.
Also fixed sqlengine's CLI display formatter to use the datetime_parse
format helpers, so temporal columns now render as "2026-04-10 14:52:21"
instead of "DATETIME(1775832688494873)".
----- 2PC durable log (crash recovery) -----
The single most dangerous gap in the distributed layer: a crash between
phase 1 (all participants PREPARE OK) and phase 2 (dispatch COMMIT)
left prepared transactions stranded on every backend with no automatic
recovery path. Fixed by a new minimal append-only WAL:
include/sql_engine/durable_txn_log.h
Format: one record per line, tab-separated:
COMMIT\t<txn_id>\t<participant1>,<participant2>,...\n
ROLLBACK\t<txn_id>\t<participant1>,<participant2>,...\n
COMPLETE\t<txn_id>\n
- log_decision() writes synchronously + fsync before phase 2 runs
- log_complete() writes synchronously + fsync after phase 2 succeeds
- scan_in_doubt() reads the log and returns every decision that has
no matching COMPLETE -- those are the transactions a DBA (or
future automatic recovery) needs to resolve
DistributedTransactionManager grew set_durable_log() (optional -- a
nullptr log disables WAL and preserves legacy behavior) and an
important semantic fix: maybe_log_complete() is now called ONLY when
phase 2 commit fully succeeded. A partial phase-2 commit leaves the
transaction in-doubt in the log, which is the correct recovery
invariant. Previously the code logged COMPLETE unconditionally, which
would have lost the in-doubt state.
Tests include the full commit happy path, phase-2 failure leaving
in-doubt, phase-1 failure recording ROLLBACK + COMPLETE, rollback
path, persistence across close/reopen, and scan of empty/missing
files.
Limitations of the MVP (documented in the header):
- Single log file, no rotation. Long-running coordinators will grow
the file indefinitely; compaction is a follow-up.
- Recovery resolution (actually contacting backends to finish the
work) lives in scan_in_doubt's caller; this class just produces
the work list.
----- Connection-level timeouts -----
The agent's review flagged "no query timeouts" as a 2PC hazard: a
wedged backend during XA PREPARE could block the entire distributed
transaction forever holding locks on every other shard. Added client-
level read/write timeouts so libmysqlclient / libpq will fail the
call after a bounded wait:
connection_pool.h, mysql_remote_executor.cpp:
MYSQL_OPT_CONNECT_TIMEOUT = 5s (was already set)
MYSQL_OPT_READ_TIMEOUT = 30s (NEW)
MYSQL_OPT_WRITE_TIMEOUT = 30s (NEW)
pgsql_remote_executor.cpp:
options='-c statement_timeout=30000' in conninfo (NEW)
All three are overridable at compile time via
SQL_ENGINE_MYSQL_{CONNECT,READ,WRITE}_TIMEOUT_SEC and
SQL_ENGINE_PG_STATEMENT_TIMEOUT_MS macros.
On top of the connection-level ceilings, DistributedTransactionManager
now has set_phase_statement_timeout_ms() which issues an explicit
SET SESSION max_execution_time (MySQL) or SET LOCAL statement_timeout
(PostgreSQL) before each phase-1 / phase-2 SQL. This lets callers
tighten the 2PC-specific timeout below the connection default without
affecting other queries on the same backend. Best-effort on pooled
connections (the SET may end up on a different physical connection
than the next statement), but the connection-level timeout is the
real ceiling.
Known not-yet-fixed:
- PostgreSQL PREPARE TRANSACTION connection-pinning issue (requires a
RemoteExecutor API change to bind a transaction to a specific
physical connection across calls; deferred).
- Automatic in-doubt recovery on startup (the WAL reports the work,
but nothing currently drives the XA COMMIT / XA ROLLBACK replay).1 parent d71571c commit b36dcaa
11 files changed
Lines changed: 1255 additions & 14 deletions
File tree
- include/sql_engine
- functions
- src/sql_engine
- tests
- tools
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
22 | 41 | | |
23 | 42 | | |
24 | 43 | | |
| |||
86 | 105 | | |
87 | 106 | | |
88 | 107 | | |
89 | | - | |
90 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
91 | 114 | | |
92 | 115 | | |
93 | 116 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
40 | 79 | | |
41 | 80 | | |
42 | 81 | | |
| |||
77 | 116 | | |
78 | 117 | | |
79 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
80 | 130 | | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
81 | 149 | | |
82 | 150 | | |
83 | 151 | | |
84 | 152 | | |
85 | 153 | | |
86 | 154 | | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
87 | 168 | | |
88 | 169 | | |
89 | 170 | | |
90 | 171 | | |
91 | 172 | | |
92 | 173 | | |
| 174 | + | |
| 175 | + | |
93 | 176 | | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
94 | 182 | | |
95 | 183 | | |
96 | 184 | | |
| |||
118 | 206 | | |
119 | 207 | | |
120 | 208 | | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
121 | 265 | | |
122 | 266 | | |
123 | 267 | | |
| |||
146 | 290 | | |
147 | 291 | | |
148 | 292 | | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
149 | 300 | | |
150 | 301 | | |
151 | 302 | | |
| |||
168 | 319 | | |
169 | 320 | | |
170 | 321 | | |
| 322 | + | |
| 323 | + | |
171 | 324 | | |
172 | 325 | | |
173 | 326 | | |
| |||
0 commit comments