tests_integration/
grpc.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15mod flight;
16mod network;
17
18use api::v1::QueryRequest;
19use api::v1::greptime_request::Request;
20use api::v1::query_request::Query;
21use common_query::OutputData;
22use common_recordbatch::RecordBatches;
23use frontend::instance::Instance;
24use servers::query_handler::grpc::GrpcQueryHandler;
25use session::context::QueryContext;
26
27#[allow(unused)]
28async fn query_and_expect(instance: &Instance, sql: &str, expected: &str) {
29    let request = Request::Query(QueryRequest {
30        query: Some(Query::Sql(sql.to_string())),
31    });
32    let output = GrpcQueryHandler::do_query(instance, request, QueryContext::arc())
33        .await
34        .unwrap();
35    let OutputData::Stream(stream) = output.data else {
36        unreachable!()
37    };
38    let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
39    let actual = recordbatches.pretty_print().unwrap();
40    assert_eq!(actual, expected, "actual: {}", actual);
41}
42
43#[cfg(test)]
44mod test {
45    use std::collections::HashMap;
46    use std::sync::Arc;
47
48    use api::v1::column::Values;
49    use api::v1::column_data_type_extension::TypeExt;
50    use api::v1::ddl_request::Expr as DdlExpr;
51    use api::v1::greptime_request::Request;
52    use api::v1::query_request::Query;
53    use api::v1::region::QueryRequest as RegionQueryRequest;
54    use api::v1::{
55        AddColumn, AddColumns, AlterTableExpr, Column, ColumnDataType, ColumnDataTypeExtension,
56        ColumnDef, CreateDatabaseExpr, CreateTableExpr, DdlRequest, DeleteRequest, DeleteRequests,
57        DropTableExpr, InsertRequest, InsertRequests, QueryRequest, SemanticType,
58        VectorTypeExtension, alter_table_expr,
59    };
60    use client::OutputData;
61    use common_catalog::consts::MITO_ENGINE;
62    use common_meta::rpc::router::region_distribution;
63    use common_query::Output;
64    use common_recordbatch::RecordBatches;
65    use frontend::instance::Instance;
66    use query::parser::QueryLanguageParser;
67    use query::query_engine::DefaultSerializer;
68    use rstest::rstest;
69    use rstest_reuse::apply;
70    use servers::query_handler::grpc::GrpcQueryHandler;
71    use session::context::{QueryContext, QueryContextBuilder};
72    use store_api::mito_engine_options::TWCS_TIME_WINDOW;
73    use store_api::storage::RegionId;
74    use substrait::{DFLogicalSubstraitConvertor, SubstraitPlan};
75
76    use super::*;
77    use crate::standalone::GreptimeDbStandaloneBuilder;
78    use crate::test_util::execute_sql_and_expect;
79    use crate::tests;
80    use crate::tests::MockDistributedInstance;
81    use crate::tests::test_util::{MockInstance, both_instances_cases, distributed, standalone};
82
83    #[tokio::test(flavor = "multi_thread")]
84    async fn test_distributed_handle_ddl_request() {
85        common_telemetry::init_default_ut_logging();
86        let instance =
87            tests::create_distributed_instance("test_distributed_handle_ddl_request").await;
88
89        test_handle_ddl_request(instance.frontend().as_ref()).await;
90
91        verify_table_is_dropped(&instance).await;
92    }
93
94    #[tokio::test(flavor = "multi_thread")]
95    async fn test_standalone_handle_ddl_request() {
96        let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_handle_ddl_request")
97            .build()
98            .await;
99        let instance = standalone.fe_instance();
100
101        test_handle_ddl_request(instance.as_ref()).await;
102    }
103
104    #[tokio::test(flavor = "multi_thread")]
105    async fn test_distributed_handle_multi_ddl_request() {
106        common_telemetry::init_default_ut_logging();
107        let instance =
108            tests::create_distributed_instance("test_distributed_handle_multi_ddl_request").await;
109
110        test_handle_multi_ddl_request(instance.frontend().as_ref()).await;
111
112        verify_table_is_dropped(&instance).await;
113    }
114
115    #[tokio::test(flavor = "multi_thread")]
116    async fn test_standalone_handle_multi_ddl_request() {
117        let standalone =
118            GreptimeDbStandaloneBuilder::new("test_standalone_handle_multi_ddl_request")
119                .build()
120                .await;
121        let instance = standalone.fe_instance();
122
123        test_handle_multi_ddl_request(instance.as_ref()).await;
124    }
125
126    async fn query(instance: &Instance, request: Request) -> Output {
127        GrpcQueryHandler::do_query(instance, request, QueryContext::arc())
128            .await
129            .unwrap()
130    }
131
132    async fn test_handle_multi_ddl_request(instance: &Instance) {
133        let request = Request::Ddl(DdlRequest {
134            expr: Some(DdlExpr::CreateDatabase(CreateDatabaseExpr {
135                catalog_name: "greptime".to_string(),
136                schema_name: "database_created_through_grpc".to_string(),
137                create_if_not_exists: true,
138                options: Default::default(),
139            })),
140        });
141        let output = query(instance, request).await;
142        assert!(matches!(output.data, OutputData::AffectedRows(1)));
143
144        let request = Request::Ddl(DdlRequest {
145            expr: Some(DdlExpr::CreateTable(CreateTableExpr {
146                catalog_name: "greptime".to_string(),
147                schema_name: "database_created_through_grpc".to_string(),
148                table_name: "table_created_through_grpc".to_string(),
149                column_defs: vec![
150                    ColumnDef {
151                        name: "a".to_string(),
152                        data_type: ColumnDataType::String as _,
153                        is_nullable: true,
154                        default_constraint: vec![],
155                        semantic_type: SemanticType::Field as i32,
156                        ..Default::default()
157                    },
158                    ColumnDef {
159                        name: "ts".to_string(),
160                        data_type: ColumnDataType::TimestampMillisecond as _,
161                        is_nullable: false,
162                        default_constraint: vec![],
163                        semantic_type: SemanticType::Timestamp as i32,
164                        ..Default::default()
165                    },
166                ],
167                time_index: "ts".to_string(),
168                engine: MITO_ENGINE.to_string(),
169                ..Default::default()
170            })),
171        });
172        let output = query(instance, request).await;
173        assert!(matches!(output.data, OutputData::AffectedRows(0)));
174
175        let request = Request::Ddl(DdlRequest {
176            expr: Some(DdlExpr::AlterTable(AlterTableExpr {
177                catalog_name: "greptime".to_string(),
178                schema_name: "database_created_through_grpc".to_string(),
179                table_name: "table_created_through_grpc".to_string(),
180                kind: Some(alter_table_expr::Kind::AddColumns(AddColumns {
181                    add_columns: vec![
182                        AddColumn {
183                            column_def: Some(ColumnDef {
184                                name: "b".to_string(),
185                                data_type: ColumnDataType::Int32 as _,
186                                is_nullable: true,
187                                default_constraint: vec![],
188                                semantic_type: SemanticType::Field as i32,
189                                ..Default::default()
190                            }),
191                            location: None,
192                            add_if_not_exists: true,
193                        },
194                        AddColumn {
195                            column_def: Some(ColumnDef {
196                                name: "a".to_string(),
197                                data_type: ColumnDataType::String as _,
198                                is_nullable: true,
199                                default_constraint: vec![],
200                                semantic_type: SemanticType::Field as i32,
201                                ..Default::default()
202                            }),
203                            location: None,
204                            add_if_not_exists: true,
205                        },
206                    ],
207                })),
208            })),
209        });
210        let output = query(instance, request).await;
211        assert!(matches!(output.data, OutputData::AffectedRows(0)));
212
213        let request = Request::Ddl(DdlRequest {
214            expr: Some(DdlExpr::AlterTable(AlterTableExpr {
215                catalog_name: "greptime".to_string(),
216                schema_name: "database_created_through_grpc".to_string(),
217                table_name: "table_created_through_grpc".to_string(),
218                kind: Some(alter_table_expr::Kind::AddColumns(AddColumns {
219                    add_columns: vec![
220                        AddColumn {
221                            column_def: Some(ColumnDef {
222                                name: "c".to_string(),
223                                data_type: ColumnDataType::Int32 as _,
224                                is_nullable: true,
225                                default_constraint: vec![],
226                                semantic_type: SemanticType::Field as i32,
227                                ..Default::default()
228                            }),
229                            location: None,
230                            add_if_not_exists: true,
231                        },
232                        AddColumn {
233                            column_def: Some(ColumnDef {
234                                name: "d".to_string(),
235                                data_type: ColumnDataType::Int32 as _,
236                                is_nullable: true,
237                                default_constraint: vec![],
238                                semantic_type: SemanticType::Field as i32,
239                                ..Default::default()
240                            }),
241                            location: None,
242                            add_if_not_exists: true,
243                        },
244                    ],
245                })),
246            })),
247        });
248        let output = query(instance, request).await;
249        assert!(matches!(output.data, OutputData::AffectedRows(0)));
250
251        let request = Request::Query(QueryRequest {
252            query: Some(Query::Sql("INSERT INTO database_created_through_grpc.table_created_through_grpc (a, b, c, d, ts) VALUES ('s', 1, 1, 1, 1672816466000)".to_string()))
253        });
254        let output = query(instance, request).await;
255        assert!(matches!(output.data, OutputData::AffectedRows(1)));
256
257        let sql = "SELECT ts, a, b FROM database_created_through_grpc.table_created_through_grpc";
258        let expected = "\
259+---------------------+---+---+
260| ts                  | a | b |
261+---------------------+---+---+
262| 2023-01-04T07:14:26 | s | 1 |
263+---------------------+---+---+";
264        query_and_expect(instance, sql, expected).await;
265
266        let request = Request::Ddl(DdlRequest {
267            expr: Some(DdlExpr::DropTable(DropTableExpr {
268                catalog_name: "greptime".to_string(),
269                schema_name: "database_created_through_grpc".to_string(),
270                table_name: "table_created_through_grpc".to_string(),
271                ..Default::default()
272            })),
273        });
274        let output = query(instance, request).await;
275        assert!(matches!(output.data, OutputData::AffectedRows(0)));
276    }
277
278    async fn test_handle_ddl_request(instance: &Instance) {
279        let request = Request::Ddl(DdlRequest {
280            expr: Some(DdlExpr::CreateDatabase(CreateDatabaseExpr {
281                catalog_name: "greptime".to_string(),
282                schema_name: "database_created_through_grpc".to_string(),
283                create_if_not_exists: true,
284                options: Default::default(),
285            })),
286        });
287        let output = query(instance, request).await;
288        assert!(matches!(output.data, OutputData::AffectedRows(1)));
289
290        let request = Request::Ddl(DdlRequest {
291            expr: Some(DdlExpr::CreateTable(CreateTableExpr {
292                catalog_name: "greptime".to_string(),
293                schema_name: "database_created_through_grpc".to_string(),
294                table_name: "table_created_through_grpc".to_string(),
295                column_defs: vec![
296                    ColumnDef {
297                        name: "a".to_string(),
298                        data_type: ColumnDataType::String as _,
299                        is_nullable: true,
300                        default_constraint: vec![],
301                        semantic_type: SemanticType::Field as i32,
302                        ..Default::default()
303                    },
304                    ColumnDef {
305                        name: "ts".to_string(),
306                        data_type: ColumnDataType::TimestampMillisecond as _,
307                        is_nullable: false,
308                        default_constraint: vec![],
309                        semantic_type: SemanticType::Timestamp as i32,
310                        ..Default::default()
311                    },
312                ],
313                time_index: "ts".to_string(),
314                engine: MITO_ENGINE.to_string(),
315                ..Default::default()
316            })),
317        });
318        let output = query(instance, request).await;
319        assert!(matches!(output.data, OutputData::AffectedRows(0)));
320
321        let request = Request::Ddl(DdlRequest {
322            expr: Some(DdlExpr::AlterTable(AlterTableExpr {
323                catalog_name: "greptime".to_string(),
324                schema_name: "database_created_through_grpc".to_string(),
325                table_name: "table_created_through_grpc".to_string(),
326                kind: Some(alter_table_expr::Kind::AddColumns(AddColumns {
327                    add_columns: vec![AddColumn {
328                        column_def: Some(ColumnDef {
329                            name: "b".to_string(),
330                            data_type: ColumnDataType::Int32 as _,
331                            is_nullable: true,
332                            default_constraint: vec![],
333                            semantic_type: SemanticType::Field as i32,
334                            ..Default::default()
335                        }),
336                        location: None,
337                        add_if_not_exists: false,
338                    }],
339                })),
340            })),
341        });
342        let output = query(instance, request).await;
343        assert!(matches!(output.data, OutputData::AffectedRows(0)));
344
345        let request = Request::Query(QueryRequest {
346            query: Some(Query::Sql("INSERT INTO database_created_through_grpc.table_created_through_grpc (a, b, ts) VALUES ('s', 1, 1672816466000)".to_string()))
347        });
348        let output = query(instance, request).await;
349        assert!(matches!(output.data, OutputData::AffectedRows(1)));
350
351        let sql = "SELECT ts, a, b FROM database_created_through_grpc.table_created_through_grpc";
352        let expected = "\
353+---------------------+---+---+
354| ts                  | a | b |
355+---------------------+---+---+
356| 2023-01-04T07:14:26 | s | 1 |
357+---------------------+---+---+";
358        query_and_expect(instance, sql, expected).await;
359
360        let request = Request::Ddl(DdlRequest {
361            expr: Some(DdlExpr::DropTable(DropTableExpr {
362                catalog_name: "greptime".to_string(),
363                schema_name: "database_created_through_grpc".to_string(),
364                table_name: "table_created_through_grpc".to_string(),
365                ..Default::default()
366            })),
367        });
368        let output = query(instance, request).await;
369        assert!(matches!(output.data, OutputData::AffectedRows(0)));
370    }
371
372    async fn verify_table_is_dropped(instance: &MockDistributedInstance) {
373        assert!(
374            instance
375                .frontend()
376                .catalog_manager()
377                .table(
378                    "greptime",
379                    "database_created_through_grpc",
380                    "table_created_through_grpc",
381                    None,
382                )
383                .await
384                .unwrap()
385                .is_none()
386        );
387    }
388
389    #[tokio::test(flavor = "multi_thread")]
390    async fn test_distributed_insert_delete_and_query() {
391        common_telemetry::init_default_ut_logging();
392
393        let instance =
394            tests::create_distributed_instance("test_distributed_insert_delete_and_query").await;
395        let frontend = instance.frontend();
396        let frontend = frontend.as_ref();
397
398        let table_name = "my_dist_table";
399        let sql = format!(
400            r"
401CREATE TABLE {table_name} (
402    a INT,
403    b STRING,
404    c JSON,
405    d VECTOR(3),
406    ts TIMESTAMP,
407    TIME INDEX (ts),
408    PRIMARY KEY (a, b, c)
409) PARTITION ON COLUMNS(a) (
410    a < 10,
411    a >= 10 AND a < 20,
412    a >= 20 AND a < 50,
413    a >= 50
414)"
415        );
416        create_table(frontend, sql).await;
417
418        test_insert_delete_and_query_on_existing_table(frontend, table_name).await;
419
420        verify_data_distribution(
421            &instance,
422            table_name,
423            HashMap::from([
424                (
425                    0u32,
426                    "\
427+---------------------+---+-------------------+
428| ts                  | a | b                 |
429+---------------------+---+-------------------+
430| 2023-01-01T07:26:12 | 1 | ts: 1672557972000 |
431| 2023-01-01T07:26:15 | 4 | ts: 1672557975000 |
432| 2023-01-01T07:26:16 | 5 | ts: 1672557976000 |
433| 2023-01-01T07:26:17 |   | ts: 1672557977000 |
434+---------------------+---+-------------------+",
435                ),
436                (
437                    1u32,
438                    "\
439+---------------------+----+-------------------+
440| ts                  | a  | b                 |
441+---------------------+----+-------------------+
442| 2023-01-01T07:26:18 | 11 | ts: 1672557978000 |
443+---------------------+----+-------------------+",
444                ),
445                (
446                    2u32,
447                    "\
448+---------------------+----+-------------------+
449| ts                  | a  | b                 |
450+---------------------+----+-------------------+
451| 2023-01-01T07:26:20 | 20 | ts: 1672557980000 |
452| 2023-01-01T07:26:21 | 21 | ts: 1672557981000 |
453| 2023-01-01T07:26:23 | 23 | ts: 1672557983000 |
454+---------------------+----+-------------------+",
455                ),
456                (
457                    3u32,
458                    "\
459+---------------------+----+-------------------+
460| ts                  | a  | b                 |
461+---------------------+----+-------------------+
462| 2023-01-01T07:26:24 | 50 | ts: 1672557984000 |
463| 2023-01-01T07:26:25 | 51 | ts: 1672557985000 |
464+---------------------+----+-------------------+",
465                ),
466            ]),
467        )
468        .await;
469
470        test_insert_delete_and_query_on_auto_created_table(frontend).await;
471
472        // Auto created table has only one region.
473        verify_data_distribution(
474            &instance,
475            "auto_created_table",
476            HashMap::from([(
477                0u32,
478                "\
479+---------------------+---+---+
480| ts                  | a | b |
481+---------------------+---+---+
482| 2023-01-01T07:26:16 |   |   |
483| 2023-01-01T07:26:17 | 6 |   |
484| 2023-01-01T07:26:18 |   | x |
485| 2023-01-01T07:26:20 |   | z |
486+---------------------+---+---+",
487            )]),
488        )
489        .await;
490    }
491
492    #[tokio::test(flavor = "multi_thread")]
493    async fn test_standalone_insert_and_query() {
494        common_telemetry::init_default_ut_logging();
495        let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_insert_and_query")
496            .build()
497            .await;
498        let instance = standalone.fe_instance();
499
500        let table_name = "my_table";
501        let sql = format!(
502            "CREATE TABLE {table_name} (a INT, b STRING, c JSON, ts TIMESTAMP, TIME INDEX (ts), PRIMARY KEY (a, b, c))"
503        );
504        create_table(instance, sql).await;
505
506        test_insert_delete_and_query_on_existing_table(instance, table_name).await;
507
508        test_insert_delete_and_query_on_auto_created_table(instance).await
509    }
510
511    async fn create_table(frontend: &Instance, sql: String) {
512        let request = Request::Query(QueryRequest {
513            query: Some(Query::Sql(sql)),
514        });
515        let output = query(frontend, request).await;
516        assert!(matches!(output.data, OutputData::AffectedRows(0)));
517    }
518
519    async fn test_insert_delete_and_query_on_existing_table(instance: &Instance, table_name: &str) {
520        let timestamp_millisecond_values = vec![
521            1672557972000,
522            1672557973000,
523            1672557974000,
524            1672557975000,
525            1672557976000,
526            1672557977000,
527            1672557978000,
528            1672557979000,
529            1672557980000,
530            1672557981000,
531            1672557982000,
532            1672557983000,
533            1672557984000,
534            1672557985000,
535            1672557986000,
536            1672557987000,
537        ];
538        let json_strings = vec![
539            r#"{ "id": 1, "name": "Alice", "age": 30, "active": true }"#.to_string(),
540            r#"{ "id": 2, "name": "Bob", "balance": 1234.56, "active": false }"#.to_string(),
541            r#"{ "id": 3, "tags": ["rust", "testing", "json"], "age": 28 }"#.to_string(),
542            r#"{ "id": 4, "metadata": { "created_at": "2024-10-30T12:00:00Z", "status": "inactive" } }"#.to_string(),
543            r#"{ "id": 5, "name": null, "phone": "+1234567890" }"#.to_string(),
544            r#"{ "id": 6, "height": 5.9, "weight": 72.5, "active": true }"#.to_string(),
545            r#"{ "id": 7, "languages": ["English", "Spanish"], "age": 29 }"#.to_string(),
546            r#"{ "id": 8, "contact": { "email": "hank@example.com", "phone": "+0987654321" } }"#.to_string(),
547            r#"{ "id": 9, "preferences": { "notifications": true, "theme": "dark" } }"#.to_string(),
548            r#"{ "id": 10, "scores": [88, 92, 76], "active": false }"#.to_string(),
549            r#"{ "id": 11, "birthday": "1996-07-20", "location": { "city": "New York", "zip": "10001" } }"#.to_string(),
550            r#"{ "id": 12, "subscription": { "type": "premium", "expires": "2025-01-01" } }"#.to_string(),
551            r#"{ "id": 13, "settings": { "volume": 0.8, "brightness": 0.6 }, "active": true }"#.to_string(),
552            r#"{ "id": 14, "notes": ["first note", "second note"], "priority": 1 }"#.to_string(),
553            r#"{ "id": 15, "transactions": [{ "amount": 500, "date": "2024-01-01" }, { "amount": -200, "date": "2024-02-01" }] }"#.to_string(),
554            r#"{ "id": 16, "transactions": [{ "amount": 500, "date": "2024-01-01" }] }"#.to_string(),
555        ];
556        let vector_values = [
557            [1.0f32, 2.0, 3.0],
558            [4.0, 5.0, 6.0],
559            [7.0, 8.0, 9.0],
560            [10.0, 11.0, 12.0],
561            [13.0, 14.0, 15.0],
562            [16.0, 17.0, 18.0],
563            [19.0, 20.0, 21.0],
564            [22.0, 23.0, 24.0],
565            [25.0, 26.0, 27.0],
566            [28.0, 29.0, 30.0],
567            [31.0, 32.0, 33.0],
568            [34.0, 35.0, 36.0],
569            [37.0, 38.0, 39.0],
570            [40.0, 41.0, 42.0],
571            [43.0, 44.0, 45.0],
572            [46.0, 47.0, 48.0],
573        ]
574        .iter()
575        .map(|x| x.iter().flat_map(|&f| f.to_le_bytes()).collect::<Vec<u8>>())
576        .collect::<Vec<_>>();
577
578        let insert = InsertRequest {
579            table_name: table_name.to_string(),
580            columns: vec![
581                Column {
582                    column_name: "a".to_string(),
583                    values: Some(Values {
584                        i32_values: vec![1, 2, 3, 4, 5, 11, 12, 20, 21, 22, 23, 50, 51, 52, 53],
585                        ..Default::default()
586                    }),
587                    null_mask: vec![32, 0],
588                    semantic_type: SemanticType::Tag as i32,
589                    datatype: ColumnDataType::Int32 as i32,
590                    ..Default::default()
591                },
592                Column {
593                    column_name: "b".to_string(),
594                    values: Some(Values {
595                        string_values: timestamp_millisecond_values
596                            .iter()
597                            .map(|x| format!("ts: {x}"))
598                            .collect(),
599                        ..Default::default()
600                    }),
601                    semantic_type: SemanticType::Tag as i32,
602                    datatype: ColumnDataType::String as i32,
603                    ..Default::default()
604                },
605                Column {
606                    column_name: "c".to_string(),
607                    values: Some(Values {
608                        string_values: json_strings,
609                        ..Default::default()
610                    }),
611                    semantic_type: SemanticType::Tag as i32,
612                    datatype: ColumnDataType::Json as i32,
613                    ..Default::default()
614                },
615                Column {
616                    column_name: "d".to_string(),
617                    values: Some(Values {
618                        binary_values: vector_values.clone(),
619                        ..Default::default()
620                    }),
621                    semantic_type: SemanticType::Field as i32,
622                    datatype: ColumnDataType::Vector as i32,
623                    datatype_extension: Some(ColumnDataTypeExtension {
624                        type_ext: Some(TypeExt::VectorType(VectorTypeExtension { dim: 3 })),
625                    }),
626                    ..Default::default()
627                },
628                Column {
629                    column_name: "ts".to_string(),
630                    values: Some(Values {
631                        timestamp_millisecond_values,
632                        ..Default::default()
633                    }),
634                    semantic_type: SemanticType::Timestamp as i32,
635                    datatype: ColumnDataType::TimestampMillisecond as i32,
636                    ..Default::default()
637                },
638            ],
639            row_count: 16,
640        };
641        let output = query(
642            instance,
643            Request::Inserts(InsertRequests {
644                inserts: vec![insert],
645            }),
646        )
647        .await;
648        assert!(matches!(output.data, OutputData::AffectedRows(16)));
649
650        let request = Request::Query(QueryRequest {
651            query: Some(Query::Sql(format!(
652                "SELECT ts, a, b, json_to_string(c) as c, d FROM {table_name} ORDER BY ts"
653            ))),
654        });
655        let output = query(instance, request.clone()).await;
656        let OutputData::Stream(stream) = output.data else {
657            unreachable!()
658        };
659        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
660        let expected = r#"+---------------------+----+-------------------+---------------------------------------------------------------------------------------------------+--------------------------+
661| ts                  | a  | b                 | c                                                                                                 | d                        |
662+---------------------+----+-------------------+---------------------------------------------------------------------------------------------------+--------------------------+
663| 2023-01-01T07:26:12 | 1  | ts: 1672557972000 | {"active":true,"age":30,"id":1,"name":"Alice"}                                                    | 0000803f0000004000004040 |
664| 2023-01-01T07:26:13 | 2  | ts: 1672557973000 | {"active":false,"balance":1234.56,"id":2,"name":"Bob"}                                            | 000080400000a0400000c040 |
665| 2023-01-01T07:26:14 | 3  | ts: 1672557974000 | {"age":28,"id":3,"tags":["rust","testing","json"]}                                                | 0000e0400000004100001041 |
666| 2023-01-01T07:26:15 | 4  | ts: 1672557975000 | {"id":4,"metadata":{"created_at":"2024-10-30T12:00:00Z","status":"inactive"}}                     | 000020410000304100004041 |
667| 2023-01-01T07:26:16 | 5  | ts: 1672557976000 | {"id":5,"name":null,"phone":"+1234567890"}                                                        | 000050410000604100007041 |
668| 2023-01-01T07:26:17 |    | ts: 1672557977000 | {"active":true,"height":5.9,"id":6,"weight":72.5}                                                 | 000080410000884100009041 |
669| 2023-01-01T07:26:18 | 11 | ts: 1672557978000 | {"age":29,"id":7,"languages":["English","Spanish"]}                                               | 000098410000a0410000a841 |
670| 2023-01-01T07:26:19 | 12 | ts: 1672557979000 | {"contact":{"email":"hank@example.com","phone":"+0987654321"},"id":8}                             | 0000b0410000b8410000c041 |
671| 2023-01-01T07:26:20 | 20 | ts: 1672557980000 | {"id":9,"preferences":{"notifications":true,"theme":"dark"}}                                      | 0000c8410000d0410000d841 |
672| 2023-01-01T07:26:21 | 21 | ts: 1672557981000 | {"active":false,"id":10,"scores":[88,92,76]}                                                      | 0000e0410000e8410000f041 |
673| 2023-01-01T07:26:22 | 22 | ts: 1672557982000 | {"birthday":"1996-07-20","id":11,"location":{"city":"New York","zip":"10001"}}                    | 0000f8410000004200000442 |
674| 2023-01-01T07:26:23 | 23 | ts: 1672557983000 | {"id":12,"subscription":{"expires":"2025-01-01","type":"premium"}}                                | 0000084200000c4200001042 |
675| 2023-01-01T07:26:24 | 50 | ts: 1672557984000 | {"active":true,"id":13,"settings":{"brightness":0.6,"volume":0.8}}                                | 000014420000184200001c42 |
676| 2023-01-01T07:26:25 | 51 | ts: 1672557985000 | {"id":14,"notes":["first note","second note"],"priority":1}                                       | 000020420000244200002842 |
677| 2023-01-01T07:26:26 | 52 | ts: 1672557986000 | {"id":15,"transactions":[{"amount":500,"date":"2024-01-01"},{"amount":-200,"date":"2024-02-01"}]} | 00002c420000304200003442 |
678| 2023-01-01T07:26:27 | 53 | ts: 1672557987000 | {"id":16,"transactions":[{"amount":500,"date":"2024-01-01"}]}                                     | 0000384200003c4200004042 |
679+---------------------+----+-------------------+---------------------------------------------------------------------------------------------------+--------------------------+"#;
680        similar_asserts::assert_eq!(recordbatches.pretty_print().unwrap(), expected);
681
682        // Checks if the encoded vector values are as expected.
683        let hex_repr_of_vector_values = vector_values.iter().map(hex::encode).collect::<Vec<_>>();
684        assert_eq!(
685            hex_repr_of_vector_values,
686            vec![
687                "0000803f0000004000004040",
688                "000080400000a0400000c040",
689                "0000e0400000004100001041",
690                "000020410000304100004041",
691                "000050410000604100007041",
692                "000080410000884100009041",
693                "000098410000a0410000a841",
694                "0000b0410000b8410000c041",
695                "0000c8410000d0410000d841",
696                "0000e0410000e8410000f041",
697                "0000f8410000004200000442",
698                "0000084200000c4200001042",
699                "000014420000184200001c42",
700                "000020420000244200002842",
701                "00002c420000304200003442",
702                "0000384200003c4200004042",
703            ]
704        );
705
706        let new_grpc_delete_request = |a, b, c, d, ts, row_count| DeleteRequest {
707            table_name: table_name.to_string(),
708            key_columns: vec![
709                Column {
710                    column_name: "a".to_string(),
711                    semantic_type: SemanticType::Tag as i32,
712                    values: Some(Values {
713                        i32_values: a,
714                        ..Default::default()
715                    }),
716                    datatype: ColumnDataType::Int32 as i32,
717                    ..Default::default()
718                },
719                Column {
720                    column_name: "b".to_string(),
721                    semantic_type: SemanticType::Tag as i32,
722                    values: Some(Values {
723                        string_values: b,
724                        ..Default::default()
725                    }),
726                    datatype: ColumnDataType::String as i32,
727                    ..Default::default()
728                },
729                Column {
730                    column_name: "c".to_string(),
731                    values: Some(Values {
732                        string_values: c,
733                        ..Default::default()
734                    }),
735                    semantic_type: SemanticType::Tag as i32,
736                    datatype: ColumnDataType::Json as i32,
737                    ..Default::default()
738                },
739                Column {
740                    column_name: "d".to_string(),
741                    values: Some(Values {
742                        binary_values: d,
743                        ..Default::default()
744                    }),
745                    semantic_type: SemanticType::Field as i32,
746                    datatype: ColumnDataType::Vector as i32,
747                    datatype_extension: Some(ColumnDataTypeExtension {
748                        type_ext: Some(TypeExt::VectorType(VectorTypeExtension { dim: 3 })),
749                    }),
750                    ..Default::default()
751                },
752                Column {
753                    column_name: "ts".to_string(),
754                    semantic_type: SemanticType::Timestamp as i32,
755                    values: Some(Values {
756                        timestamp_millisecond_values: ts,
757                        ..Default::default()
758                    }),
759                    datatype: ColumnDataType::TimestampMillisecond as i32,
760                    ..Default::default()
761                },
762            ],
763            row_count,
764        };
765        let delete1 = new_grpc_delete_request(
766            vec![2, 12, 22, 52],
767            vec![
768                "ts: 1672557973000".to_string(),
769                "ts: 1672557979000".to_string(),
770                "ts: 1672557982000".to_string(),
771                "ts: 1672557986000".to_string(),
772            ],
773            vec![
774                r#"{ "id": 2, "name": "Bob", "balance": 1234.56, "active": false }"#.to_string(),
775                r#"{ "id": 8, "contact": { "email": "hank@example.com", "phone": "+0987654321" } }"#.to_string(),
776                r#"{ "id": 11, "birthday": "1996-07-20", "location": { "city": "New York", "zip": "10001" } }"#.to_string(),
777                r#"{ "id": 15, "transactions": [{ "amount": 500, "date": "2024-01-01" }, { "amount": -200, "date": "2024-02-01" }] }"#.to_string(),
778            ],
779            vec![
780                [4.0f32, 5.0, 6.0].iter().flat_map(|f| f.to_le_bytes()).collect::<Vec<u8>>(),
781                [22.0f32, 23.0, 24.0].iter().flat_map(|f| f.to_le_bytes()).collect::<Vec<u8>>(),
782                [31.0f32, 32.0, 33.0].iter().flat_map(|f| f.to_le_bytes()).collect::<Vec<u8>>(),
783                [43.0f32, 44.0, 45.0].iter().flat_map(|f| f.to_le_bytes()).collect::<Vec<u8>>(),
784            ],
785            vec![1672557973000, 1672557979000, 1672557982000, 1672557986000],
786            4,
787        );
788        let delete2 = new_grpc_delete_request(
789            vec![3, 53],
790            vec![
791                "ts: 1672557974000".to_string(),
792                "ts: 1672557987000".to_string(),
793            ],
794            vec![
795                r#"{ "id": 3, "tags": ["rust", "testing", "json"], "age": 28 }"#.to_string(),
796                r#"{ "id": 16, "transactions": [{ "amount": 500, "date": "2024-01-01" }] }"#
797                    .to_string(),
798            ],
799            vec![
800                [7.0f32, 8.0, 9.0]
801                    .iter()
802                    .flat_map(|f| f.to_le_bytes())
803                    .collect::<Vec<u8>>(),
804                [46.0f32, 47.0, 48.0]
805                    .iter()
806                    .flat_map(|f| f.to_le_bytes())
807                    .collect::<Vec<u8>>(),
808            ],
809            vec![1672557974000, 1672557987000],
810            2,
811        );
812        let output = query(
813            instance,
814            Request::Deletes(DeleteRequests {
815                deletes: vec![delete1, delete2],
816            }),
817        )
818        .await;
819        assert!(matches!(output.data, OutputData::AffectedRows(6)));
820
821        let output = query(instance, request).await;
822        let OutputData::Stream(stream) = output.data else {
823            unreachable!()
824        };
825        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
826        let expected = r#"+---------------------+----+-------------------+-------------------------------------------------------------------------------+--------------------------+
827| ts                  | a  | b                 | c                                                                             | d                        |
828+---------------------+----+-------------------+-------------------------------------------------------------------------------+--------------------------+
829| 2023-01-01T07:26:12 | 1  | ts: 1672557972000 | {"active":true,"age":30,"id":1,"name":"Alice"}                                | 0000803f0000004000004040 |
830| 2023-01-01T07:26:15 | 4  | ts: 1672557975000 | {"id":4,"metadata":{"created_at":"2024-10-30T12:00:00Z","status":"inactive"}} | 000020410000304100004041 |
831| 2023-01-01T07:26:16 | 5  | ts: 1672557976000 | {"id":5,"name":null,"phone":"+1234567890"}                                    | 000050410000604100007041 |
832| 2023-01-01T07:26:17 |    | ts: 1672557977000 | {"active":true,"height":5.9,"id":6,"weight":72.5}                             | 000080410000884100009041 |
833| 2023-01-01T07:26:18 | 11 | ts: 1672557978000 | {"age":29,"id":7,"languages":["English","Spanish"]}                           | 000098410000a0410000a841 |
834| 2023-01-01T07:26:20 | 20 | ts: 1672557980000 | {"id":9,"preferences":{"notifications":true,"theme":"dark"}}                  | 0000c8410000d0410000d841 |
835| 2023-01-01T07:26:21 | 21 | ts: 1672557981000 | {"active":false,"id":10,"scores":[88,92,76]}                                  | 0000e0410000e8410000f041 |
836| 2023-01-01T07:26:23 | 23 | ts: 1672557983000 | {"id":12,"subscription":{"expires":"2025-01-01","type":"premium"}}            | 0000084200000c4200001042 |
837| 2023-01-01T07:26:24 | 50 | ts: 1672557984000 | {"active":true,"id":13,"settings":{"brightness":0.6,"volume":0.8}}            | 000014420000184200001c42 |
838| 2023-01-01T07:26:25 | 51 | ts: 1672557985000 | {"id":14,"notes":["first note","second note"],"priority":1}                   | 000020420000244200002842 |
839+---------------------+----+-------------------+-------------------------------------------------------------------------------+--------------------------+"#;
840        similar_asserts::assert_eq!(recordbatches.pretty_print().unwrap(), expected);
841    }
842
843    async fn verify_data_distribution(
844        instance: &MockDistributedInstance,
845        table_name: &str,
846        expected_distribution: HashMap<u32, &str>,
847    ) {
848        let table = instance
849            .frontend()
850            .catalog_manager()
851            .table("greptime", "public", table_name, None)
852            .await
853            .unwrap()
854            .unwrap();
855        let table_id = table.table_info().ident.table_id;
856        let table_route_value = instance
857            .table_metadata_manager()
858            .table_route_manager()
859            .table_route_storage()
860            .get(table_id)
861            .await
862            .unwrap()
863            .unwrap();
864
865        let region_to_dn_map = region_distribution(
866            table_route_value
867                .region_routes()
868                .expect("physical table route"),
869        )
870        .iter()
871        .map(|(k, v)| (v.leader_regions[0], *k))
872        .collect::<HashMap<u32, u64>>();
873        assert!(region_to_dn_map.len() <= instance.datanodes().len());
874
875        let stmt = QueryLanguageParser::parse_sql(
876            &format!("SELECT ts, a, b FROM {table_name} ORDER BY ts"),
877            &QueryContext::arc(),
878        )
879        .unwrap();
880        let plan = instance
881            .frontend()
882            .statement_executor()
883            .plan(&stmt, QueryContext::arc())
884            .await
885            .unwrap();
886        let plan = DFLogicalSubstraitConvertor
887            .encode(&plan, DefaultSerializer)
888            .unwrap();
889
890        for (region, dn) in region_to_dn_map.iter() {
891            let region_server = instance.datanodes().get(dn).unwrap().region_server();
892
893            let region_id = RegionId::new(table_id, *region);
894
895            let stream = region_server
896                .handle_remote_read(
897                    RegionQueryRequest {
898                        region_id: region_id.as_u64(),
899                        plan: plan.to_vec(),
900                        ..Default::default()
901                    },
902                    QueryContext::arc(),
903                )
904                .await
905                .unwrap();
906
907            let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
908            let actual = recordbatches.pretty_print().unwrap();
909
910            let expected = expected_distribution.get(region).unwrap();
911            assert_eq!(&actual, expected);
912        }
913    }
914
915    async fn test_insert_delete_and_query_on_auto_created_table(instance: &Instance) {
916        let insert = InsertRequest {
917            table_name: "auto_created_table".to_string(),
918            columns: vec![
919                Column {
920                    column_name: "a".to_string(),
921                    values: Some(Values {
922                        i32_values: vec![4, 6],
923                        ..Default::default()
924                    }),
925                    null_mask: vec![2],
926                    semantic_type: SemanticType::Field as i32,
927                    datatype: ColumnDataType::Int32 as i32,
928                    ..Default::default()
929                },
930                Column {
931                    column_name: "c".to_string(),
932                    values: Some(Values {
933                        string_values: vec![
934                            r#"{ "id": 1, "name": "Alice", "age": 30, "active": true }"#
935                                .to_string(),
936                            r#"{ "id": 2, "name": "Bob", "balance": 1234.56, "active": false }"#
937                                .to_string(),
938                        ],
939                        ..Default::default()
940                    }),
941                    null_mask: vec![2],
942                    semantic_type: SemanticType::Field as i32,
943                    datatype: ColumnDataType::Json as i32,
944                    ..Default::default()
945                },
946                Column {
947                    column_name: "ts".to_string(),
948                    values: Some(Values {
949                        timestamp_millisecond_values: vec![
950                            1672557975000,
951                            1672557976000,
952                            1672557977000,
953                        ],
954                        ..Default::default()
955                    }),
956                    semantic_type: SemanticType::Timestamp as i32,
957                    datatype: ColumnDataType::TimestampMillisecond as i32,
958                    ..Default::default()
959                },
960            ],
961            row_count: 3,
962        };
963
964        // Test auto create not existed table upon insertion.
965        let request = Request::Inserts(InsertRequests {
966            inserts: vec![insert],
967        });
968        let output = query(instance, request).await;
969        assert!(matches!(output.data, OutputData::AffectedRows(3)));
970
971        let insert = InsertRequest {
972            table_name: "auto_created_table".to_string(),
973            columns: vec![
974                Column {
975                    column_name: "b".to_string(),
976                    values: Some(Values {
977                        string_values: vec!["x".to_string(), "z".to_string()],
978                        ..Default::default()
979                    }),
980                    null_mask: vec![2],
981                    semantic_type: SemanticType::Field as i32,
982                    datatype: ColumnDataType::String as i32,
983                    ..Default::default()
984                },
985                Column {
986                    column_name: "ts".to_string(),
987                    values: Some(Values {
988                        timestamp_millisecond_values: vec![
989                            1672557978000,
990                            1672557979000,
991                            1672557980000,
992                        ],
993                        ..Default::default()
994                    }),
995                    semantic_type: SemanticType::Timestamp as i32,
996                    datatype: ColumnDataType::TimestampMillisecond as i32,
997                    ..Default::default()
998                },
999            ],
1000            row_count: 3,
1001        };
1002
1003        // Test auto add not existed column upon insertion.
1004        let request = Request::Inserts(InsertRequests {
1005            inserts: vec![insert],
1006        });
1007        let output = query(instance, request).await;
1008        assert!(matches!(output.data, OutputData::AffectedRows(3)));
1009
1010        let request = Request::Query(QueryRequest {
1011            query: Some(Query::Sql(
1012                "SELECT ts, a, b, json_to_string(c) as c FROM auto_created_table order by ts"
1013                    .to_string(),
1014            )),
1015        });
1016        let output = query(instance, request.clone()).await;
1017        let OutputData::Stream(stream) = output.data else {
1018            unreachable!()
1019        };
1020        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
1021        let expected = r#"+---------------------+---+---+--------------------------------------------------------+
1022| ts                  | a | b | c                                                      |
1023+---------------------+---+---+--------------------------------------------------------+
1024| 2023-01-01T07:26:15 | 4 |   | {"active":true,"age":30,"id":1,"name":"Alice"}         |
1025| 2023-01-01T07:26:16 |   |   |                                                        |
1026| 2023-01-01T07:26:17 | 6 |   | {"active":false,"balance":1234.56,"id":2,"name":"Bob"} |
1027| 2023-01-01T07:26:18 |   | x |                                                        |
1028| 2023-01-01T07:26:19 |   |   |                                                        |
1029| 2023-01-01T07:26:20 |   | z |                                                        |
1030+---------------------+---+---+--------------------------------------------------------+"#;
1031        similar_asserts::assert_eq!(recordbatches.pretty_print().unwrap(), expected);
1032
1033        let delete = DeleteRequest {
1034            table_name: "auto_created_table".to_string(),
1035            key_columns: vec![Column {
1036                column_name: "ts".to_string(),
1037                values: Some(Values {
1038                    timestamp_millisecond_values: vec![1672557975000, 1672557979000],
1039                    ..Default::default()
1040                }),
1041                semantic_type: SemanticType::Timestamp as i32,
1042                datatype: ColumnDataType::TimestampMillisecond as i32,
1043                ..Default::default()
1044            }],
1045            row_count: 2,
1046        };
1047
1048        let output = query(
1049            instance,
1050            Request::Deletes(DeleteRequests {
1051                deletes: vec![delete],
1052            }),
1053        )
1054        .await;
1055        assert!(matches!(output.data, OutputData::AffectedRows(2)));
1056
1057        let output = query(instance, request).await;
1058        let OutputData::Stream(stream) = output.data else {
1059            unreachable!()
1060        };
1061        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
1062        let expected = r#"+---------------------+---+---+--------------------------------------------------------+
1063| ts                  | a | b | c                                                      |
1064+---------------------+---+---+--------------------------------------------------------+
1065| 2023-01-01T07:26:16 |   |   |                                                        |
1066| 2023-01-01T07:26:17 | 6 |   | {"active":false,"balance":1234.56,"id":2,"name":"Bob"} |
1067| 2023-01-01T07:26:18 |   | x |                                                        |
1068| 2023-01-01T07:26:20 |   | z |                                                        |
1069+---------------------+---+---+--------------------------------------------------------+"#;
1070        similar_asserts::assert_eq!(recordbatches.pretty_print().unwrap(), expected);
1071    }
1072
1073    #[tokio::test(flavor = "multi_thread")]
1074    async fn test_promql_query() {
1075        let standalone = GreptimeDbStandaloneBuilder::new("test_standalone_promql_query")
1076            .build()
1077            .await;
1078        let instance = standalone.fe_instance();
1079
1080        let table_name = "my_table";
1081        let sql = format!(
1082            "CREATE TABLE {table_name} (h string, a double, ts TIMESTAMP, TIME INDEX (ts), PRIMARY KEY(h))"
1083        );
1084        create_table(instance, sql).await;
1085
1086        let insert = InsertRequest {
1087            table_name: table_name.to_string(),
1088            columns: vec![
1089                Column {
1090                    column_name: "h".to_string(),
1091                    values: Some(Values {
1092                        string_values: vec![
1093                            "t".to_string(),
1094                            "t".to_string(),
1095                            "t".to_string(),
1096                            "t".to_string(),
1097                            "t".to_string(),
1098                            "t".to_string(),
1099                            "t".to_string(),
1100                            "t".to_string(),
1101                        ],
1102                        ..Default::default()
1103                    }),
1104                    semantic_type: SemanticType::Tag as i32,
1105                    datatype: ColumnDataType::String as i32,
1106                    ..Default::default()
1107                },
1108                Column {
1109                    column_name: "a".to_string(),
1110                    values: Some(Values {
1111                        f64_values: vec![1f64, 11f64, 20f64, 22f64, 50f64, 55f64, 99f64],
1112                        ..Default::default()
1113                    }),
1114                    null_mask: vec![4],
1115                    semantic_type: SemanticType::Field as i32,
1116                    datatype: ColumnDataType::Float64 as i32,
1117                    ..Default::default()
1118                },
1119                Column {
1120                    column_name: "ts".to_string(),
1121                    values: Some(Values {
1122                        timestamp_millisecond_values: vec![
1123                            1672557972000,
1124                            1672557973000,
1125                            1672557974000,
1126                            1672557975000,
1127                            1672557976000,
1128                            1672557977000,
1129                            1672557978000,
1130                            1672557979000,
1131                        ],
1132                        ..Default::default()
1133                    }),
1134                    semantic_type: SemanticType::Timestamp as i32,
1135                    datatype: ColumnDataType::TimestampMillisecond as i32,
1136                    ..Default::default()
1137                },
1138            ],
1139            row_count: 8,
1140        };
1141
1142        let request = Request::Inserts(InsertRequests {
1143            inserts: vec![insert],
1144        });
1145        let output = query(instance, request).await;
1146        assert!(matches!(output.data, OutputData::AffectedRows(8)));
1147
1148        let request = Request::Query(QueryRequest {
1149            query: Some(Query::PromRangeQuery(api::v1::PromRangeQuery {
1150                query: "my_table".to_owned(),
1151                start: "1672557973".to_owned(),
1152                end: "1672557978".to_owned(),
1153                step: "1s".to_owned(),
1154                lookback: "5m".to_string(),
1155            })),
1156        });
1157        let output = query(instance, request).await;
1158        let OutputData::Stream(stream) = output.data else {
1159            unreachable!()
1160        };
1161        let recordbatches = RecordBatches::try_collect(stream).await.unwrap();
1162        let expected = "\
1163+---+------+---------------------+
1164| h | a    | ts                  |
1165+---+------+---------------------+
1166| t | 11.0 | 2023-01-01T07:26:13 |
1167| t |      | 2023-01-01T07:26:14 |
1168| t | 20.0 | 2023-01-01T07:26:15 |
1169| t | 22.0 | 2023-01-01T07:26:16 |
1170| t | 50.0 | 2023-01-01T07:26:17 |
1171| t | 55.0 | 2023-01-01T07:26:18 |
1172+---+------+---------------------+";
1173        assert_eq!(recordbatches.pretty_print().unwrap(), expected);
1174    }
1175
1176    #[apply(both_instances_cases)]
1177    async fn test_extra_external_table_options(instance: Arc<dyn MockInstance>) {
1178        common_telemetry::init_default_ut_logging();
1179        let frontend = instance.frontend();
1180        let instance = frontend.as_ref();
1181
1182        let insert = InsertRequest {
1183            table_name: "auto_created_table".to_string(),
1184            columns: vec![
1185                Column {
1186                    column_name: "a".to_string(),
1187                    values: Some(Values {
1188                        i32_values: vec![4, 6],
1189                        ..Default::default()
1190                    }),
1191                    null_mask: vec![2],
1192                    semantic_type: SemanticType::Field as i32,
1193                    datatype: ColumnDataType::Int32 as i32,
1194                    ..Default::default()
1195                },
1196                Column {
1197                    column_name: "c".to_string(),
1198                    values: Some(Values {
1199                        string_values: vec![
1200                            r#"{ "id": 1, "name": "Alice", "age": 30, "active": true }"#
1201                                .to_string(),
1202                            r#"{ "id": 2, "name": "Bob", "balance": 1234.56, "active": false }"#
1203                                .to_string(),
1204                        ],
1205                        ..Default::default()
1206                    }),
1207                    null_mask: vec![2],
1208                    semantic_type: SemanticType::Field as i32,
1209                    datatype: ColumnDataType::Json as i32,
1210                    ..Default::default()
1211                },
1212                Column {
1213                    column_name: "ts".to_string(),
1214                    values: Some(Values {
1215                        timestamp_millisecond_values: vec![
1216                            1672557975000,
1217                            1672557976000,
1218                            1672557977000,
1219                        ],
1220                        ..Default::default()
1221                    }),
1222                    semantic_type: SemanticType::Timestamp as i32,
1223                    datatype: ColumnDataType::TimestampMillisecond as i32,
1224                    ..Default::default()
1225                },
1226            ],
1227            row_count: 3,
1228        };
1229        let request = Request::Inserts(InsertRequests {
1230            inserts: vec![insert],
1231        });
1232
1233        let ctx = Arc::new(
1234            QueryContextBuilder::default()
1235                .set_extension(TWCS_TIME_WINDOW.to_string(), "1d".to_string())
1236                .build(),
1237        );
1238        let output = GrpcQueryHandler::do_query(instance, request, ctx)
1239            .await
1240            .unwrap();
1241        assert!(matches!(output.data, OutputData::AffectedRows(3)));
1242
1243        let sql = "show create table auto_created_table";
1244        let expected = r#"+--------------------+---------------------------------------------------+
1245| Table              | Create Table                                      |
1246+--------------------+---------------------------------------------------+
1247| auto_created_table | CREATE TABLE IF NOT EXISTS "auto_created_table" ( |
1248|                    |   "a" INT NULL,                                   |
1249|                    |   "c" JSON NULL,                                  |
1250|                    |   "ts" TIMESTAMP(3) NOT NULL,                     |
1251|                    |   TIME INDEX ("ts")                               |
1252|                    | )                                                 |
1253|                    |                                                   |
1254|                    | ENGINE=mito                                       |
1255|                    | WITH(                                             |
1256|                    |   'comment' = 'Created on insertion',             |
1257|                    |   'compaction.twcs.time_window' = '1d',           |
1258|                    |   'compaction.type' = 'twcs'                      |
1259|                    | )                                                 |
1260+--------------------+---------------------------------------------------+"#;
1261        execute_sql_and_expect(&frontend, sql, expected).await;
1262    }
1263}