@@ -62,6 +62,121 @@ describe("task events v2", () => {
6262 } ,
6363 ] ) ;
6464
65+ const readColumnKinds = ch . reader . query ( {
66+ name : "read-task-event-attribute-column-kinds" ,
67+ query : `SELECT name, default_kind, default_expression
68+ FROM system.columns
69+ WHERE database = 'trigger_dev'
70+ AND table = 'task_events_v2'
71+ AND name IN ('attributes', 'attributes_text')
72+ ORDER BY name` ,
73+ schema : z . object ( {
74+ name : z . string ( ) ,
75+ default_kind : z . string ( ) ,
76+ default_expression : z . string ( ) ,
77+ } ) ,
78+ } ) ;
79+ const [ columnError , columns ] = await readColumnKinds ( { } ) ;
80+ expect ( columnError ) . toBeNull ( ) ;
81+ expect ( columns ) . toEqual ( [
82+ {
83+ name : "attributes" ,
84+ default_kind : "EPHEMERAL" ,
85+ default_expression : "defaultValueOfTypeName('JSON')" ,
86+ } ,
87+ {
88+ name : "attributes_text" ,
89+ default_kind : "MATERIALIZED" ,
90+ default_expression : "toJSONString(attributes)" ,
91+ } ,
92+ ] ) ;
93+
94+ const readRemovedIndexes = ch . reader . query ( {
95+ name : "read-removed-task-event-text-indexes" ,
96+ query : `SELECT name
97+ FROM system.data_skipping_indices
98+ WHERE database = 'trigger_dev'
99+ AND table = 'task_events_v2'
100+ AND name IN ('idx_attributes_text_search', 'idx_message_text_search')
101+ ORDER BY name` ,
102+ schema : z . object ( { name : z . string ( ) } ) ,
103+ } ) ;
104+ const [ indexError , indexes ] = await readRemovedIndexes ( { } ) ;
105+ expect ( indexError ) . toBeNull ( ) ;
106+ expect ( indexes ) . toEqual ( [ ] ) ;
107+ }
108+ ) ;
109+
110+ clickhouseTest (
111+ "restores stored attributes for implicit inserts on rollback" ,
112+ async ( { clickhouseClient } ) => {
113+ const table = "trigger_dev.task_events_ephemeral_rollback_test" ;
114+ await clickhouseClient . command ( {
115+ query : `CREATE TABLE ${ table }
116+ (
117+ id UInt64,
118+ attributes JSON EPHEMERAL,
119+ attributes_text String MATERIALIZED toJSONString(attributes)
120+ )
121+ ENGINE = MergeTree
122+ ORDER BY id` ,
123+ } ) ;
124+
125+ try {
126+ await clickhouseClient . insert ( {
127+ table,
128+ columns : [ "id" , "attributes" ] ,
129+ format : "JSONEachRow" ,
130+ values : [ { id : 1 , attributes : { before : "rollback" } } ] ,
131+ } ) ;
132+
133+ await clickhouseClient . command ( {
134+ query : `ALTER TABLE ${ table }
135+ RENAME COLUMN attributes TO attributes_ephemeral,
136+ ADD COLUMN attributes JSON CODEC(ZSTD(1)) AFTER id,
137+ MODIFY COLUMN attributes_text String MATERIALIZED toJSONString(attributes),
138+ DROP COLUMN attributes_ephemeral` ,
139+ } ) ;
140+
141+ await clickhouseClient . insert ( {
142+ table,
143+ format : "JSONEachRow" ,
144+ values : [ { id : 2 , attributes : { after : "rollback" } } ] ,
145+ } ) ;
146+
147+ const columnsResult = await clickhouseClient . query ( {
148+ query : `SELECT default_kind, compression_codec
149+ FROM system.columns
150+ WHERE database = 'trigger_dev'
151+ AND table = 'task_events_ephemeral_rollback_test'
152+ AND name = 'attributes'` ,
153+ format : "JSONEachRow" ,
154+ } ) ;
155+ expect ( await columnsResult . json ( ) ) . toEqual ( [
156+ { default_kind : "" , compression_codec : "CODEC(ZSTD(1))" } ,
157+ ] ) ;
158+
159+ const rowsResult = await clickhouseClient . query ( {
160+ query : `SELECT id, attributes_text, toJSONString(attributes) AS attributes_json
161+ FROM ${ table }
162+ ORDER BY id` ,
163+ format : "JSONEachRow" ,
164+ } ) ;
165+ expect ( await rowsResult . json ( ) ) . toEqual ( [
166+ {
167+ id : 1 ,
168+ attributes_text : '{"before":"rollback"}' ,
169+ attributes_json : "{}" ,
170+ } ,
171+ {
172+ id : 2 ,
173+ attributes_text : '{"after":"rollback"}' ,
174+ attributes_json : '{"after":"rollback"}' ,
175+ } ,
176+ ] ) ;
177+ } finally {
178+ await clickhouseClient . command ( { query : `DROP TABLE IF EXISTS ${ table } ` } ) ;
179+ }
65180 }
66181 ) ;
67182} ) ;
0 commit comments