Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/sql.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,8 @@ type charset_name = Named of string | Binary | Ascii | Unicode

type ttl_option =
[ `TtlSet of string * int * string
| `TtlEnable of string ] [@@deriving show {with_path=false}]
| `TtlEnable of string
| `TtlJobInterval of string ] [@@deriving show {with_path=false}]

module Alter_column_pg = struct
type t =
Expand Down
1 change: 1 addition & 0 deletions lib/sql_lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ let keywords =
"recursive", RECURSIVE;
"ttl", TTL;
"ttl_enable", TTL_ENABLE;
"ttl_job_interval", TTL_JOB_INTERVAL;
"remove", REMOVE;
"type", TYPE "type";
] in (* more *)
Expand Down
3 changes: 2 additions & 1 deletion lib/sql_parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
FIRST_VALUE LAST_VALUE NTH_VALUE PARTITION ROWS RANGE UNBOUNDED PRECEDING FOLLOWING CURRENT ROW
CAST GENERATED ALWAYS VIRTUAL STORED STATEMENT DOUBLECOLON QSTN TWO_QSTN INSTANT INPLACE COPY ALGORITHM RECURSIVE
SHARED EXCLUSIVE NONE
TTL TTL_ENABLE REMOVE CACHE NOCACHE
TTL TTL_ENABLE TTL_JOB_INTERVAL REMOVE CACHE NOCACHE
%token FUNCTION PROCEDURE LANGUAGE RETURNS OUT INOUT BEGIN COMMENT
%token <string> EXTENSION SCHEMA VERSION
%token SECOND_MICROSECOND MINUTE_MICROSECOND MINUTE_SECOND
Expand Down Expand Up @@ -442,6 +442,7 @@ alter_option:
ttl_option: TTL EQUAL col=ident PLUS INTERVAL n=INTEGER unit=INTERVAL_UNIT
{ `TtlSet (col, n, unit) }
| TTL_ENABLE EQUAL v=TEXT { `TtlEnable v }
| TTL_JOB_INTERVAL EQUAL v=TEXT { `TtlJobInterval v }
index_or_key: INDEX | KEY { }
index_type:
| index_or_key { Sql.Plain_idx }
Expand Down
20 changes: 13 additions & 7 deletions lib/syntax.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1862,20 +1862,26 @@ let rec eval (stmt:Sql.stmt) =
Tables.index_rename name ~old_name ~new_name
| `AddConstraint _ | `DropConstraint _ | `Cache _ | `NoCache _ -> ()
| `TtlOptions (opts, _) ->
let expr, enabled =
List.fold_left (fun (expr, enabled) -> function
| `TtlSet (col, n, unit) -> Some (col, n, String.uppercase_ascii unit), enabled
| `TtlEnable v -> expr, Some (String.uppercase_ascii v <> "OFF"))
(None, None) opts
let expr, enabled, job_interval =
List.fold_left (fun (expr, enabled, job_interval) -> function
| `TtlSet (col, n, unit) -> Some (col, n, String.uppercase_ascii unit), enabled, job_interval
| `TtlEnable v -> expr, Some (String.uppercase_ascii v <> "OFF"), job_interval
| `TtlJobInterval v -> expr, enabled, Some v)
(None, None, None) opts
in
let prev = Tables.get_ttl name in
let ttl_enabled =
Option.default (Option.map_default (fun (t : Tables.table_ttl) -> t.ttl_enabled) true prev) enabled
in
let ttl_job_interval =
match job_interval with
| Some _ -> job_interval
| None -> Option.map_default (fun (t : Tables.table_ttl) -> t.ttl_job_interval) None prev
in
Tables.set_ttl name @@
Option.map_default
(fun (ttl_col, ttl_n, ttl_unit) -> Some { Tables.ttl_col; ttl_n; ttl_unit; ttl_enabled })
(Option.map (fun (t : Tables.table_ttl) -> { t with ttl_enabled }) prev)
(fun (ttl_col, ttl_n, ttl_unit) -> Some { Tables.ttl_col; ttl_n; ttl_unit; ttl_enabled; ttl_job_interval })
(Option.map (fun (t : Tables.table_ttl) -> { t with ttl_enabled; ttl_job_interval }) prev)
expr
| `RemoveTtl _ -> Tables.set_ttl name None
| `Default_or_convert_to (cs, collation) ->
Expand Down
2 changes: 1 addition & 1 deletion lib/tables.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type table = Sql.table

type table_charset = { charset : Sql.charset_name; collation : string option }

type table_ttl = { ttl_col : string; ttl_n : int; ttl_unit : string; ttl_enabled : bool }
type table_ttl = { ttl_col : string; ttl_n : int; ttl_unit : string; ttl_enabled : bool; ttl_job_interval : string option }

module SMap = Map.Make(String)

Expand Down
3 changes: 2 additions & 1 deletion src/gen_migrations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ let action_to_sql_fragment ~default_sql_lookup (action : Sql.alter_action) = mat
|> List.map (function
| `TtlSet (col, n, unit) ->
sprintf "TTL = %s + INTERVAL %d %s" (quote_id col) n (String.uppercase_ascii unit)
| `TtlEnable v -> sprintf "TTL_ENABLE = '%s'" v)
| `TtlEnable v -> sprintf "TTL_ENABLE = '%s'" v
| `TtlJobInterval v -> sprintf "TTL_JOB_INTERVAL = '%s'" v)
|> String.concat " "
| `RemoveTtl _ -> "REMOVE TTL"
| `Cache _ -> "CACHE"
Expand Down
18 changes: 16 additions & 2 deletions src/schema_diff.ml
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,29 @@ let diff_charset =
[`Default_or_convert_to (charset, Option.map Gen_migrations.loc collation)])
[])

let default_tidb_ttl_job_interval = "1h"

let ttl_options_of (t : Tables.table_ttl) =
[ `TtlSet (t.ttl_col, t.ttl_n, t.ttl_unit);
`TtlEnable (if t.ttl_enabled then "ON" else "OFF") ]
@ Option.map_default (fun v -> [`TtlJobInterval v]) [] t.ttl_job_interval

let diff_ttl =
diff_property (fun t -> t.Tables.tbl_ttl)
(Option.map_default (fun t -> [`TtlOptions (ttl_options_of t, (0, 0))])
[`RemoveTtl (0, 0)])

let diff_table ~from_ ~to_ =
let to_ =
match from_.Tables.tbl_ttl, to_.Tables.tbl_ttl with
| Some { ttl_job_interval = Some _; _ },
Some ({ ttl_job_interval = None; _ } as ttl) ->
let ttl =
{ ttl with ttl_job_interval = Some default_tidb_ttl_job_interval }
in
{ to_ with tbl_ttl = Some ttl }
| _ -> to_
in
diff_columns ~from_ ~to_ @ diff_pk ~from_ ~to_
@ diff_indexes ~from_ ~to_ @ diff_charset ~from_ ~to_ @ diff_ttl ~from_ ~to_

Expand Down Expand Up @@ -313,8 +326,9 @@ let canonical ts =
in
let ttl_sig =
Option.map_default
(fun ({ ttl_col; ttl_n; ttl_unit; ttl_enabled } : Tables.table_ttl) ->
sprintf "%s+%d %s/%s" ttl_col ttl_n ttl_unit (if ttl_enabled then "on" else "off"))
(fun ({ ttl_col; ttl_n; ttl_unit; ttl_enabled; ttl_job_interval } : Tables.table_ttl) ->
sprintf "%s+%d %s/%s/%s" ttl_col ttl_n ttl_unit (if ttl_enabled then "on" else "off")
(Option.default default_tidb_ttl_job_interval ttl_job_interval))
""
in
let table_sig (t : Tables.stored_table) =
Expand Down
16 changes: 16 additions & 0 deletions test/cram/test.t
Original file line number Diff line number Diff line change
Expand Up @@ -3665,6 +3665,22 @@ Quoted `cache` still works as an identifier:
> SELECT `cache` FROM bar;
> EOF

TTL_JOB_INTERVAL is accepted on TiDB, standalone or with other TTL options:
$ sqlgg -gen caml -no-header -dialect=tidb - <<'EOF' >/dev/null
> CREATE TABLE foo (id INT NOT NULL, created_at TIMESTAMP NOT NULL);
> ALTER TABLE foo TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON' TTL_JOB_INTERVAL = '24h';
> ALTER TABLE foo TTL_JOB_INTERVAL = '30m';
> EOF

TTL_JOB_INTERVAL is rejected on non-TiDB dialects:
$ sqlgg -gen caml -no-header -dialect=mysql - <<'EOF' 2>&1
> CREATE TABLE foo (id INT NOT NULL, created_at TIMESTAMP NOT NULL);
> ALTER TABLE foo TTL_JOB_INTERVAL = '30m';
> EOF
Feature Ttl is not supported for dialect MySQL (supported by: TiDB) at TTL_JOB_INTERVAL = '30m'
Errors encountered, no code generated
[1]

Composite: a choice nested inside another choice — every level is wrapped
independently, so precedence is protected at each depth:
$ sqlgg -gen caml -params unnamed -no-header - <<'EOF' 2>&1 | grep -F 'WHERE FALSE AND' | head -1
Expand Down
16 changes: 16 additions & 0 deletions test/cram/test_migrations/diff-ttl.t/run.t
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ Changing the interval: the down restores the previous expression:
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 90 DAY TTL_ENABLE = 'ON';
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON';

Changing TTL_JOB_INTERVAL from its implicit 1h default is reversible:

$ sqlgg -no-header -dialect tidb -diff -now 20260101000000 -gen sql -base initial.sql -base initial.ttl.sql -target initial.sql -target initial.ttl.sql -target target.ttl-job-24h.sql
-- [sqlgg] generated
-- [sqlgg] id=20260101000000_alter_foo_set_ttl
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON' TTL_JOB_INTERVAL = '24h';
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON' TTL_JOB_INTERVAL = '1h';

Returning from an explicit interval to the implicit default also emits 1h:

$ sqlgg -no-header -dialect tidb -diff -now 20260101000000 -gen sql -base initial.sql -base initial.ttl.sql -base target.ttl-job-24h.sql -target initial.sql -target initial.ttl.sql
-- [sqlgg] generated
-- [sqlgg] id=20260101000000_alter_foo_set_ttl
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON' TTL_JOB_INTERVAL = '1h';
ALTER TABLE `foo` TTL = `created_at` + INTERVAL 6 MONTH TTL_ENABLE = 'ON' TTL_JOB_INTERVAL = '24h';

TTL survives schema materialization (and parses back, closing the loop):

$ sqlgg -no-header -dialect tidb -gen sql -base initial.sql -base initial.ttl.sql
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE foo TTL_JOB_INTERVAL = '24h';