Skip to content

Commit 3f6e4e4

Browse files
authored
ide: tablefunc extension stub + composite type support (#1035)
1 parent 8ef93da commit 3f6e4e4

3 files changed

Lines changed: 177 additions & 7 deletions

File tree

crates/squawk_ide/src/generated/extensions/postgis.sql

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/squawk_ide/src/generated/extensions/tablefunc.sql

Lines changed: 59 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/xtask/src/sync_builtins.rs

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,20 @@ use std::path::Path;
55
use std::process::{Command, Stdio};
66

77
use anyhow::{Context, Result, bail};
8-
use serde::Deserialize;
8+
use serde::de::DeserializeOwned;
9+
use serde::{Deserialize, Deserializer};
910

1011
use crate::path::project_root;
1112

13+
fn deserialize_json_string<'de, D, T>(deserializer: D) -> Result<T, D::Error>
14+
where
15+
D: Deserializer<'de>,
16+
T: DeserializeOwned,
17+
{
18+
let s = String::deserialize(deserializer)?;
19+
serde_json::from_str(&s).map_err(serde::de::Error::custom)
20+
}
21+
1222
const PG_TEMP_SCHEMA_SQL: &str = "create schema pg_temp;\n\n";
1323

1424
#[derive(Deserialize)]
@@ -129,7 +139,8 @@ struct RelationQuery {
129139
relkind: String,
130140
description: String,
131141
extension_name: String,
132-
columns: String,
142+
#[serde(deserialize_with = "deserialize_json_string")]
143+
columns: Vec<Column>,
133144
}
134145

135146
impl Query for RelationQuery {
@@ -212,6 +223,49 @@ order by n.nspname, p.proname, pg_get_function_arguments(p.oid), pg_get_function
212223
";
213224
}
214225

226+
#[derive(Deserialize)]
227+
struct CompositeTypeQuery {
228+
schema: String,
229+
name: String,
230+
description: String,
231+
extension_name: String,
232+
#[serde(deserialize_with = "deserialize_json_string")]
233+
columns: Vec<Column>,
234+
}
235+
236+
impl Query for CompositeTypeQuery {
237+
const QUERY: &'static str = r"
238+
select
239+
n.nspname as schema,
240+
t.typname as name,
241+
coalesce(d.description, '') as description,
242+
coalesce(ext.extname, 'builtins') as extension_name,
243+
json_agg(
244+
json_build_object(
245+
'name', a.attname,
246+
'data_type', format_type(a.atttypid, a.atttypmod)
247+
)
248+
order by a.attnum
249+
) as columns
250+
from pg_type t
251+
join pg_namespace n on n.oid = t.typnamespace
252+
join pg_class c on c.oid = t.typrelid
253+
join pg_attribute a on a.attrelid = c.oid
254+
left join pg_description d on d.objoid = t.oid and d.classoid = 'pg_type'::regclass
255+
left join pg_depend dep on dep.classid = 'pg_type'::regclass and dep.objid = t.oid and dep.objsubid = 0 and dep.deptype = 'e'
256+
left join pg_extension ext on ext.oid = dep.refobjid
257+
where n.nspname not like 'pg_temp%'
258+
and n.nspname not like 'pg_toast%'
259+
and (n.nspname != 'public' or ext.extname is not null)
260+
and t.typtype = 'c'
261+
and c.relkind = 'c'
262+
and a.attnum > 0
263+
and not a.attisdropped
264+
group by t.oid, n.nspname, t.typname, d.description, ext.extname
265+
order by n.nspname, t.typname, t.oid;
266+
";
267+
}
268+
215269
#[derive(Deserialize)]
216270
struct OperatorQuery {
217271
schema: String,
@@ -282,6 +336,7 @@ begin
282336
'plpgsql',
283337
'postgis',
284338
'postgres_fdw',
339+
'tablefunc',
285340
'vector'
286341
] loop
287342
execute format('create extension if not exists %I', extension_name);
@@ -363,6 +418,31 @@ impl WriteSql for RangeTypeDef {
363418
}
364419
}
365420

421+
struct CompositeTypeDef {
422+
schema: String,
423+
name: String,
424+
description: String,
425+
columns: Vec<Column>,
426+
}
427+
428+
impl WriteSql for CompositeTypeDef {
429+
fn write_sql<W: Write>(&self, f: &mut W) -> io::Result<()> {
430+
write_description(f, &self.description)?;
431+
writeln!(f, "create type {}.{} as (", self.schema, self.name)?;
432+
for (index, column) in self.columns.iter().enumerate() {
433+
let comma = if index + 1 < self.columns.len() {
434+
","
435+
} else {
436+
""
437+
};
438+
writeln!(f, " {} {}{comma}", column.name, column.data_type)?;
439+
}
440+
writeln!(f, ");")?;
441+
writeln!(f)?;
442+
Ok(())
443+
}
444+
}
445+
366446
struct TableDef {
367447
schema: String,
368448
name: String,
@@ -552,6 +632,7 @@ struct Module {
552632
schemas: Vec<SchemaDef>,
553633
types: Vec<TypeDef>,
554634
range_types: Vec<RangeTypeDef>,
635+
composite_types: Vec<CompositeTypeDef>,
555636
tables: Vec<TableDef>,
556637
views: Vec<ViewDef>,
557638
functions: Vec<FunctionDef>,
@@ -572,6 +653,10 @@ impl Module {
572653
range_type.write_sql(f)?;
573654
}
574655

656+
for composite_type in &self.composite_types {
657+
composite_type.write_sql(f)?;
658+
}
659+
575660
for table in &self.tables {
576661
table.write_sql(f)?;
577662
}
@@ -663,21 +748,35 @@ fn query_types(modules: &mut BTreeMap<String, Module>) -> Result<()> {
663748
Ok(())
664749
}
665750

751+
fn query_composite_types(modules: &mut BTreeMap<String, Module>) -> Result<()> {
752+
for row in CompositeTypeQuery::run()? {
753+
modules
754+
.entry(row.extension_name)
755+
.or_default()
756+
.composite_types
757+
.push(CompositeTypeDef {
758+
columns: row.columns,
759+
description: row.description,
760+
name: row.name,
761+
schema: row.schema,
762+
});
763+
}
764+
765+
Ok(())
766+
}
767+
666768
fn query_relations(modules: &mut BTreeMap<String, Module>) -> Result<()> {
667769
for row in RelationQuery::run()? {
668-
let columns: Vec<Column> =
669-
serde_json::from_str(&row.columns).context("expected valid column json")?;
670-
671770
let module = modules.entry(row.extension_name).or_default();
672771
match row.relkind.as_str() {
673772
"r" => module.tables.push(TableDef {
674-
columns,
773+
columns: row.columns,
675774
description: row.description,
676775
name: row.name,
677776
schema: row.schema,
678777
}),
679778
"v" => module.views.push(ViewDef {
680-
columns,
779+
columns: row.columns,
681780
description: row.description,
682781
name: row.name,
683782
schema: row.schema,
@@ -759,6 +858,7 @@ pub(crate) fn sync_builtins() -> Result<()> {
759858

760859
query_schemas(&mut modules)?;
761860
query_types(&mut modules)?;
861+
query_composite_types(&mut modules)?;
762862
query_relations(&mut modules)?;
763863
query_functions(&mut modules)?;
764864
query_operators(&mut modules)?;

0 commit comments

Comments
 (0)