@@ -50,6 +50,52 @@ use tokio::io::AsyncBufReadExt;
50
50
lazy_static ! {
51
51
static ref SHOW_DATABASES_DESC : RelationDesc =
52
52
{ RelationDesc :: empty( ) . add_column( "Database" , ScalarType :: String ) } ;
53
+ static ref SHOW_INDEXES_DESC : RelationDesc = RelationDesc :: new(
54
+ RelationType :: new( vec![
55
+ ColumnType :: new( ScalarType :: String ) ,
56
+ ColumnType :: new( ScalarType :: String ) ,
57
+ ColumnType :: new( ScalarType :: String ) . nullable( true ) ,
58
+ ColumnType :: new( ScalarType :: String ) . nullable( true ) ,
59
+ ColumnType :: new( ScalarType :: Bool ) ,
60
+ ColumnType :: new( ScalarType :: Int64 ) ,
61
+ ] ) ,
62
+ vec![
63
+ "Source_or_view" ,
64
+ "Key_name" ,
65
+ "Column_name" ,
66
+ "Expression" ,
67
+ "Null" ,
68
+ "Seq_in_index" ,
69
+ ]
70
+ . into_iter( )
71
+ . map( Some ) ,
72
+ ) ;
73
+ static ref SHOW_COLUMNS_DESC : RelationDesc = RelationDesc :: empty( )
74
+ . add_column( "Field" , ScalarType :: String )
75
+ . add_column( "Nullable" , ScalarType :: String )
76
+ . add_column( "Type" , ScalarType :: String ) ;
77
+ }
78
+
79
+ pub fn make_show_objects_desc (
80
+ object_type : ObjectType ,
81
+ materialized : bool ,
82
+ full : bool ,
83
+ ) -> RelationDesc {
84
+ let col_name = object_type_as_plural_str ( object_type) ;
85
+ if full {
86
+ let mut relation_desc = RelationDesc :: empty ( )
87
+ . add_column ( col_name, ScalarType :: String )
88
+ . add_column ( "TYPE" , ScalarType :: String ) ;
89
+ if ObjectType :: View == object_type {
90
+ relation_desc = relation_desc. add_column ( "QUERYABLE" , ScalarType :: Bool ) ;
91
+ }
92
+ if !materialized && ( ObjectType :: View == object_type || ObjectType :: Source == object_type) {
93
+ relation_desc = relation_desc. add_column ( "MATERIALIZED" , ScalarType :: Bool ) ;
94
+ }
95
+ relation_desc
96
+ } else {
97
+ RelationDesc :: empty ( ) . add_column ( col_name, ScalarType :: String )
98
+ }
53
99
}
54
100
55
101
pub fn describe_statement (
@@ -124,40 +170,9 @@ pub fn describe_statement(
124
170
vec ! [ ] ,
125
171
) ,
126
172
127
- Statement :: ShowColumns { .. } => (
128
- Some (
129
- RelationDesc :: empty ( )
130
- . add_column ( "Field" , ScalarType :: String )
131
- . add_column ( "Nullable" , ScalarType :: String )
132
- . add_column ( "Type" , ScalarType :: String ) ,
133
- ) ,
134
- vec ! [ ] ,
135
- ) ,
173
+ Statement :: ShowColumns { .. } => ( Some ( SHOW_COLUMNS_DESC . clone ( ) ) , vec ! [ ] ) ,
136
174
137
- Statement :: ShowIndexes { .. } => (
138
- Some ( RelationDesc :: new (
139
- RelationType :: new ( vec ! [
140
- ColumnType :: new( ScalarType :: String ) ,
141
- ColumnType :: new( ScalarType :: String ) ,
142
- ColumnType :: new( ScalarType :: String ) . nullable( true ) ,
143
- ColumnType :: new( ScalarType :: String ) . nullable( true ) ,
144
- ColumnType :: new( ScalarType :: Bool ) ,
145
- ColumnType :: new( ScalarType :: Int64 ) ,
146
- ] ) ,
147
- vec ! [
148
- "Source_or_view" ,
149
- "Key_name" ,
150
- "Column_name" ,
151
- "Expression" ,
152
- "Null" ,
153
- "Seq_in_index" ,
154
- ]
155
- . iter ( )
156
- . map ( |s| Some ( * s) )
157
- . collect :: < Vec < _ > > ( ) ,
158
- ) ) ,
159
- vec ! [ ] ,
160
- ) ,
175
+ Statement :: ShowIndexes { .. } => ( Some ( SHOW_INDEXES_DESC . clone ( ) ) , vec ! [ ] ) ,
161
176
162
177
Statement :: ShowDatabases { .. } => ( Some ( SHOW_DATABASES_DESC . clone ( ) ) , vec ! [ ] ) ,
163
178
@@ -166,28 +181,10 @@ pub fn describe_statement(
166
181
full,
167
182
materialized,
168
183
..
169
- } => {
170
- let col_name = object_type_as_plural_str ( object_type) ;
171
- (
172
- Some ( if full {
173
- let mut relation_desc = RelationDesc :: empty ( )
174
- . add_column ( col_name, ScalarType :: String )
175
- . add_column ( "TYPE" , ScalarType :: String ) ;
176
- if ObjectType :: View == object_type {
177
- relation_desc = relation_desc. add_column ( "QUERYABLE" , ScalarType :: Bool ) ;
178
- }
179
- if !materialized
180
- && ( ObjectType :: View == object_type || ObjectType :: Source == object_type)
181
- {
182
- relation_desc = relation_desc. add_column ( "MATERIALIZED" , ScalarType :: Bool ) ;
183
- }
184
- relation_desc
185
- } else {
186
- RelationDesc :: empty ( ) . add_column ( col_name, ScalarType :: String )
187
- } ) ,
188
- vec ! [ ] ,
189
- )
190
- }
184
+ } => (
185
+ Some ( make_show_objects_desc ( object_type, materialized, full) ) ,
186
+ vec ! [ ] ,
187
+ ) ,
191
188
Statement :: ShowVariable { variable, .. } => {
192
189
if variable. value == unicase:: Ascii :: new ( "ALL" ) {
193
190
(
@@ -281,7 +278,7 @@ pub fn handle_statement(
281
278
from,
282
279
materialized,
283
280
filter,
284
- } => handle_show_objects ( scx, extended, full, materialized, ot, from, filter) ,
281
+ } => handle_show_objects ( scx, extended, full, materialized, ot, from, filter. as_ref ( ) ) ,
285
282
Statement :: ShowIndexes {
286
283
extended,
287
284
table_name,
@@ -346,17 +343,13 @@ fn handle_tail(scx: &StatementContext, from: ObjectName) -> Result<Plan, failure
346
343
}
347
344
}
348
345
349
- fn handle_show_databases (
346
+ fn finish_show_where (
350
347
scx : & StatementContext ,
351
348
filter : Option < & ShowStatementFilter > ,
349
+ rows : Vec < Vec < Datum > > ,
350
+ desc : & RelationDesc ,
352
351
) -> Result < Plan , failure:: Error > {
353
- let rows = scx
354
- . catalog
355
- . databases ( )
356
- . map ( |database| vec ! [ Datum :: from( database) ] )
357
- . collect ( ) ;
358
-
359
- let ( r, finishing) = query:: plan_show_where ( scx, filter, rows, & SHOW_DATABASES_DESC ) ?;
352
+ let ( r, finishing) = query:: plan_show_where ( scx, filter, rows, desc) ?;
360
353
361
354
Ok ( Plan :: Peek {
362
355
source : r. decorrelate ( ) ?,
@@ -366,32 +359,45 @@ fn handle_show_databases(
366
359
} )
367
360
}
368
361
362
+ fn handle_show_databases (
363
+ scx : & StatementContext ,
364
+ filter : Option < & ShowStatementFilter > ,
365
+ ) -> Result < Plan , failure:: Error > {
366
+ let rows = scx
367
+ . catalog
368
+ . databases ( )
369
+ . map ( |database| vec ! [ Datum :: from( database) ] )
370
+ . collect ( ) ;
371
+
372
+ finish_show_where ( scx, filter, rows, & SHOW_DATABASES_DESC )
373
+ }
374
+
369
375
fn handle_show_objects (
370
376
scx : & StatementContext ,
371
377
extended : bool ,
372
378
full : bool ,
373
379
materialized : bool ,
374
380
object_type : ObjectType ,
375
381
from : Option < ObjectName > ,
376
- filter : Option < ShowStatementFilter > ,
382
+ filter : Option < & ShowStatementFilter > ,
377
383
) -> Result < Plan , failure:: Error > {
378
384
let classify_id = |id| match id {
379
385
GlobalId :: System ( _) => "SYSTEM" ,
380
386
GlobalId :: User ( _) => "USER" ,
381
387
} ;
382
- let make_row = |name : & str , class| {
388
+ let arena = RowArena :: new ( ) ;
389
+ let make_row = |name : & str , class : & str | {
383
390
if full {
384
- Row :: pack ( & [ Datum :: from ( name) , Datum :: from ( class) ] )
391
+ vec ! [
392
+ Datum :: from( arena. push_string( name. to_string( ) ) ) ,
393
+ Datum :: from( arena. push_string( class. to_string( ) ) ) ,
394
+ ]
385
395
} else {
386
- Row :: pack ( & [ Datum :: from ( name) ] )
396
+ vec ! [ Datum :: from( arena . push_string ( name. to_string ( ) ) ) ]
387
397
}
388
398
} ;
389
399
390
400
if let ObjectType :: Schema = object_type {
391
- if filter. is_some ( ) {
392
- bail ! ( "SHOW SCHEMAS ... {LIKE | WHERE} is not supported" ) ;
393
- }
394
-
395
401
let schemas = if let Some ( from) = from {
396
402
if from. 0 . len ( ) != 1 {
397
403
bail ! (
@@ -427,15 +433,15 @@ fn handle_show_objects(
427
433
rows. push ( make_row ( name, "SYSTEM" ) ) ;
428
434
}
429
435
}
430
- rows. sort_unstable_by ( move |a, b| a. unpack_first ( ) . cmp ( & b. unpack_first ( ) ) ) ;
431
- Ok ( Plan :: SendRows ( rows) )
436
+ // TODO(justin): it's unfortunate that we call make_show_objects_desc twice, I think we
437
+ // should be able to restructure this so that it only gets called once.
438
+ finish_show_where (
439
+ scx,
440
+ filter,
441
+ rows,
442
+ & make_show_objects_desc ( object_type, materialized, full) ,
443
+ )
432
444
} else {
433
- let like_regex = match filter {
434
- Some ( ShowStatementFilter :: Like ( pattern) ) => like_pattern:: build_regex ( & pattern) ?,
435
- Some ( ShowStatementFilter :: Where ( _) ) => bail ! ( "SHOW ... WHERE is not supported" ) ,
436
- None => like_pattern:: build_regex ( "%" ) ?,
437
- } ;
438
-
439
445
let empty_schema = BTreeMap :: new ( ) ;
440
446
let items = if let Some ( mut from) = from {
441
447
if from. 0 . len ( ) > 2 {
@@ -469,12 +475,20 @@ fn handle_show_objects(
469
475
let filtered_items = items
470
476
. iter ( )
471
477
. map ( |( name, id) | ( name, scx. catalog . get_by_id ( id) ) )
472
- . filter ( |( _name, entry) | {
473
- object_type_matches ( object_type, entry. item ( ) )
474
- && like_regex. is_match ( & entry. name ( ) . to_string ( ) )
475
- } ) ;
478
+ . filter ( |( _name, entry) | object_type_matches ( object_type, entry. item ( ) ) ) ;
476
479
477
480
if object_type == ObjectType :: View || object_type == ObjectType :: Source {
481
+ // TODO(justin): we can't handle SHOW ... WHERE here yet because the coordinator adds
482
+ // extra columns to this result that we don't have access to here yet. This could be
483
+ // fixed by passing down this extra catalog info somehow.
484
+ let like_regex = match filter {
485
+ Some ( ShowStatementFilter :: Like ( pattern) ) => like_pattern:: build_regex ( & pattern) ?,
486
+ Some ( ShowStatementFilter :: Where ( _) ) => bail ! ( "SHOW ... WHERE is not supported" ) ,
487
+ None => like_pattern:: build_regex ( "%" ) ?,
488
+ } ;
489
+
490
+ let filtered_items = filtered_items
491
+ . filter ( |( _name, entry) | like_regex. is_match ( & entry. name ( ) . to_string ( ) ) ) ;
478
492
Ok ( Plan :: ShowViews {
479
493
ids : filtered_items
480
494
. map ( |( name, entry) | ( name. clone ( ) , entry. id ( ) ) )
@@ -484,11 +498,16 @@ fn handle_show_objects(
484
498
limit_materialized : materialized,
485
499
} )
486
500
} else {
487
- let mut rows = filtered_items
501
+ let rows = filtered_items
488
502
. map ( |( name, entry) | make_row ( name, classify_id ( entry. id ( ) ) ) )
489
503
. collect :: < Vec < _ > > ( ) ;
490
- rows. sort_unstable_by ( move |a, b| a. unpack_first ( ) . cmp ( & b. unpack_first ( ) ) ) ;
491
- Ok ( Plan :: SendRows ( rows) )
504
+
505
+ finish_show_where (
506
+ scx,
507
+ filter,
508
+ rows,
509
+ & make_show_objects_desc ( object_type, materialized, full) ,
510
+ )
492
511
}
493
512
}
494
513
}
@@ -502,9 +521,6 @@ fn handle_show_indexes(
502
521
if extended {
503
522
bail ! ( "SHOW EXTENDED INDEXES is not supported" )
504
523
}
505
- if filter. is_some ( ) {
506
- bail ! ( "SHOW INDEXES ... WHERE is not supported" ) ;
507
- }
508
524
let from_name = scx. resolve_name ( from_name) ?;
509
525
let from_entry = scx. catalog . get ( & from_name) ?;
510
526
if !object_type_matches ( ObjectType :: View , from_entry. item ( ) )
@@ -516,6 +532,7 @@ fn handle_show_indexes(
516
532
from_entry. item( ) . type_string( )
517
533
) ;
518
534
}
535
+ let arena = RowArena :: new ( ) ;
519
536
let rows = scx
520
537
. catalog
521
538
. iter ( )
@@ -541,7 +558,6 @@ fn handle_show_indexes(
541
558
for ( i, ( key_expr, key_sql) ) in keys. iter ( ) . zip_eq ( key_sqls) . enumerate ( ) {
542
559
let desc = scx. catalog . get_by_id ( & on) . desc ( ) . unwrap ( ) ;
543
560
let key_sql = key_sql. to_string ( ) ;
544
- let arena = RowArena :: new ( ) ;
545
561
let ( col_name, func) = match key_expr {
546
562
expr:: ScalarExpr :: Column ( i) => {
547
563
let col_name = match desc. get_unambiguous_name ( * i) {
@@ -552,21 +568,22 @@ fn handle_show_indexes(
552
568
}
553
569
_ => ( Datum :: Null , Datum :: String ( arena. push_string ( key_sql) ) ) ,
554
570
} ;
555
- row_subset. push ( Row :: pack ( & vec ! [
556
- Datum :: String ( & from_entry. name( ) . to_string( ) ) ,
557
- Datum :: String ( & entry. name( ) . to_string( ) ) ,
571
+ row_subset. push ( vec ! [
572
+ Datum :: String ( arena . push_string ( from_entry. name( ) . to_string( ) ) ) ,
573
+ Datum :: String ( arena . push_string ( entry. name( ) . to_string( ) ) ) ,
558
574
col_name,
559
575
func,
560
576
Datum :: from( key_expr. typ( desc. typ( ) ) . nullable) ,
561
577
Datum :: from( ( i + 1 ) as i64 ) ,
562
- ] ) ) ;
578
+ ] ) ;
563
579
}
564
580
row_subset
565
581
}
566
582
_ => unreachable ! ( ) ,
567
583
} )
568
584
. collect ( ) ;
569
- Ok ( Plan :: SendRows ( rows) )
585
+
586
+ finish_show_where ( scx, filter, rows, & SHOW_INDEXES_DESC )
570
587
}
571
588
572
589
/// Create an immediate result that describes all the columns for the given table
@@ -583,27 +600,25 @@ fn handle_show_columns(
583
600
if full {
584
601
bail ! ( "SHOW FULL COLUMNS is not supported" ) ;
585
602
}
586
- if filter. is_some ( ) {
587
- bail ! ( "SHOW COLUMNS ... { LIKE | WHERE } is not supported" ) ;
588
- }
589
603
604
+ let arena = RowArena :: new ( ) ;
590
605
let table_name = scx. resolve_name ( table_name) ?;
591
- let column_descriptions : Vec < _ > = scx
606
+ let rows : Vec < _ > = scx
592
607
. catalog
593
608
. get ( & table_name) ?
594
609
. desc ( ) ?
595
610
. iter ( )
596
611
. map ( |( name, typ) | {
597
612
let name = name. map ( |n| n. to_string ( ) ) ;
598
- Row :: pack ( & [
599
- Datum :: String ( name. as_deref ( ) . unwrap_or ( "?" ) ) ,
613
+ vec ! [
614
+ Datum :: String ( name. map ( |n| arena . push_string ( n ) ) . unwrap_or( "?" ) ) ,
600
615
Datum :: String ( if typ. nullable { "YES" } else { "NO" } ) ,
601
616
Datum :: String ( pgrepr:: Type :: from( & typ. scalar_type) . name( ) ) ,
602
- ] )
617
+ ]
603
618
} )
604
619
. collect ( ) ;
605
620
606
- Ok ( Plan :: SendRows ( column_descriptions ) )
621
+ finish_show_where ( scx , filter , rows , & SHOW_COLUMNS_DESC )
607
622
}
608
623
609
624
fn handle_show_create_view (
0 commit comments