From 88e28fd586a5e6e4e177471b903ba7dd1084a48e Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 11 Jul 2026 22:16:56 +0000 Subject: [PATCH] feat(inflection): add dns_1123() for Kubernetes DNS-1123 label normalization Single readable SQL function that lowercases, maps ':' to '--' and '_' to '-', strips invalid chars, trims hyphens, caps at 63 chars (DNS label limit), and drops trailing non-alphanumerics after truncation. Mirrors the TS toK8sName() used to derive Knative/K8s object names. --- packages/inflection/Makefile | 2 +- .../inflection/__tests__/inflection.test.ts | 30 + .../inflection/procedures/dns_1123.sql | 64 ++ packages/inflection/pgpm-inflection.control | 2 +- packages/inflection/pgpm.plan | 3 +- .../inflection/procedures/dns_1123.sql | 7 + ...0.15.5.sql => pgpm-inflection--0.30.0.sql} | 831 ++++-------------- .../inflection/procedures/dns_1123.sql | 7 + 8 files changed, 292 insertions(+), 654 deletions(-) create mode 100644 packages/inflection/deploy/schemas/inflection/procedures/dns_1123.sql create mode 100644 packages/inflection/revert/schemas/inflection/procedures/dns_1123.sql rename packages/inflection/sql/{pgpm-inflection--0.15.5.sql => pgpm-inflection--0.30.0.sql} (64%) create mode 100644 packages/inflection/verify/schemas/inflection/procedures/dns_1123.sql diff --git a/packages/inflection/Makefile b/packages/inflection/Makefile index 8acaf844..451e94c7 100644 --- a/packages/inflection/Makefile +++ b/packages/inflection/Makefile @@ -1,5 +1,5 @@ EXTENSION = pgpm-inflection -DATA = sql/pgpm-inflection--0.15.5.sql +DATA = sql/pgpm-inflection--0.30.0.sql PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) diff --git a/packages/inflection/__tests__/inflection.test.ts b/packages/inflection/__tests__/inflection.test.ts index d1bb15c9..c436bd8e 100644 --- a/packages/inflection/__tests__/inflection.test.ts +++ b/packages/inflection/__tests__/inflection.test.ts @@ -221,4 +221,34 @@ describe('inflection', () => { { name: 'information', result: 'information' } ] ); + + cases( + 'dns_1123', + async (opts: { name: string; result: string }) => { + const { dns_1123 } = await pg.one( + 'SELECT * FROM inflection.dns_1123($1)', + [opts.name] + ); + expect(dns_1123).toEqual(opts.result); + }, + [ + { name: 'api', result: 'api' }, + { name: 'MyService', result: 'myservice' }, + { name: 'my_service', result: 'my-service' }, + { name: 'org:api', result: 'org--api' }, + { name: 'Hello, World!', result: 'helloworld' }, + { name: '__leading', result: 'leading' }, + { name: 'trailing__', result: 'trailing' }, + { name: '---', result: '' }, + { + name: 'a'.repeat(80), + result: 'a'.repeat(63) + }, + { + // truncation lands on a '-'; trailing non-alphanumerics are dropped + name: `${'a'.repeat(62)}-bcd`, + result: 'a'.repeat(62) + } + ] + ); }); diff --git a/packages/inflection/deploy/schemas/inflection/procedures/dns_1123.sql b/packages/inflection/deploy/schemas/inflection/procedures/dns_1123.sql new file mode 100644 index 00000000..e479a404 --- /dev/null +++ b/packages/inflection/deploy/schemas/inflection/procedures/dns_1123.sql @@ -0,0 +1,64 @@ +-- Deploy schemas/inflection/procedures/dns_1123 to pg + +-- requires: schemas/inflection/schema + +-- Normalizes a value into a Kubernetes DNS-1123 label (RFC 1123): +-- lowercase alphanumerics and '-', at most 63 characters, and no leading or +-- trailing '-'. Used to derive Knative/K8s object names from arbitrary slugs. + +BEGIN; + +CREATE FUNCTION inflection.dns_1123 (value text) + RETURNS text + AS $$ + WITH lowercased AS ( + SELECT + lower(value) AS value +), +-- ':' delimits namespaced identifiers; map to '--' so the boundary survives +namespaced AS ( + SELECT + replace(value, ':', '--') AS value +FROM + lowercased +), +hyphenated AS ( + SELECT + replace(value, '_', '-') AS value +FROM + namespaced +), +stripped AS ( + SELECT + regexp_replace(value, '[^a-z0-9-]', '', 'g') AS value +FROM + hyphenated +), +trimmed AS ( + SELECT + regexp_replace(value, '^-+|-+$', '', 'g') AS value +FROM + stripped +), +truncated AS ( + SELECT + "left"(value, 63) AS value +FROM + trimmed +), +-- truncation can leave a dangling '-'; drop any trailing non-alphanumerics +final AS ( + SELECT + regexp_replace(value, '[^a-z0-9]+$', '') AS value +FROM + truncated +) +SELECT + value +FROM + final; +$$ +LANGUAGE SQL +STRICT IMMUTABLE; + +COMMIT; diff --git a/packages/inflection/pgpm-inflection.control b/packages/inflection/pgpm-inflection.control index 1049a69b..5924bccf 100644 --- a/packages/inflection/pgpm-inflection.control +++ b/packages/inflection/pgpm-inflection.control @@ -1,6 +1,6 @@ # pgpm-inflection extension comment = 'pgpm-inflection extension' -default_version = '0.15.5' +default_version = '0.30.0' module_pathname = '$libdir/pgpm-inflection' requires = 'plpgsql,unaccent,pgpm-verify' relocatable = false diff --git a/packages/inflection/pgpm.plan b/packages/inflection/pgpm.plan index d289d21f..81d7a02b 100644 --- a/packages/inflection/pgpm.plan +++ b/packages/inflection/pgpm.plan @@ -1,7 +1,7 @@ %syntax-version=1.0.0 %project=pgpm-inflection %uri=pgpm-inflection - + schemas/inflection/schema 2017-08-11T08:11:51Z skitch # add schemas/inflection/schema schemas/inflection/procedures/no_consecutive_caps [schemas/inflection/schema] 2017-08-11T08:11:51Z skitch # add schemas/inflection/procedures/no_consecutive_caps schemas/inflection/procedures/pg_slugify [schemas/inflection/schema schemas/inflection/procedures/no_consecutive_caps] 2017-08-11T08:11:51Z skitch # add schemas/inflection/procedures/pg_slugify @@ -18,3 +18,4 @@ schemas/inflection/procedures/singular [schemas/inflection/schema schemas/inflec schemas/inflection/procedures/slugify [schemas/inflection/schema] 2017-08-11T08:11:51Z skitch # add schemas/inflection/procedures/slugify schemas/inflection/tables/inflection_rules/fixtures/1589249334312_fixture [schemas/inflection/schema schemas/inflection/tables/inflection_rules/table] 2017-08-11T08:11:51Z skitch # add schemas/inflection/tables/inflection_rules/fixtures/1589249334312_fixture schemas/inflection/tables/inflection_rules/indexes/inflection_rules_type_idx [schemas/inflection/schema schemas/inflection/tables/inflection_rules/table] 2017-08-11T08:11:51Z skitch # add schemas/inflection/tables/inflection_rules/indexes/inflection_rules_type_idx +schemas/inflection/procedures/dns_1123 [schemas/inflection/schema] 2026-07-11T22:14:14Z constructive # Kubernetes DNS-1123 label normalization diff --git a/packages/inflection/revert/schemas/inflection/procedures/dns_1123.sql b/packages/inflection/revert/schemas/inflection/procedures/dns_1123.sql new file mode 100644 index 00000000..bfa119f7 --- /dev/null +++ b/packages/inflection/revert/schemas/inflection/procedures/dns_1123.sql @@ -0,0 +1,7 @@ +-- Revert schemas/inflection/procedures/dns_1123 from pg + +BEGIN; + +DROP FUNCTION inflection.dns_1123(text); + +COMMIT; diff --git a/packages/inflection/sql/pgpm-inflection--0.15.5.sql b/packages/inflection/sql/pgpm-inflection--0.30.0.sql similarity index 64% rename from packages/inflection/sql/pgpm-inflection--0.15.5.sql rename to packages/inflection/sql/pgpm-inflection--0.30.0.sql index ee69d58a..2be901a9 100644 --- a/packages/inflection/sql/pgpm-inflection--0.15.5.sql +++ b/packages/inflection/sql/pgpm-inflection--0.30.0.sql @@ -382,660 +382,189 @@ INSERT INTO inflection.inflection_rules ( test, replacement ) VALUES -( - 'plural', - '^(m|wom)en$', - NULL -), -( - 'plural', - '(pe)ople$', - NULL -), -( - 'plural', - '(child)ren$', - NULL -), -( - 'plural', - '([ti])a$', - NULL -), -( - 'plural', - '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$', - NULL -), -( - 'plural', - '(database)s$', - NULL -), -( - 'plural', - '(drive)s$', - NULL -), -( - 'plural', - '(hi|ti)ves$', - NULL -), -( - 'plural', - '(curve)s$', - NULL -), -( - 'plural', - '([lr])ves$', - NULL -), -( - 'plural', - '([^fo])ves$', - NULL -), -( - 'plural', - '([^aeiouy]|qu)ies$', - NULL -), -( - 'plural', - '(s)eries$', - NULL -), -( - 'plural', - '(m)ovies$', - NULL -), -( - 'plural', - '(x|ch|ss|sh)es$', - NULL -), -( - 'plural', - '([m|l])ice$', - NULL -), -( - 'plural', - '(bus)es$', - NULL -), -( - 'plural', - '(o)es$', - NULL -), -( - 'plural', - '(shoe)s$', - NULL -), -( - 'plural', - '(cris|ax|test)es$', - NULL -), -( - 'plural', - '(octop|vir)uses$', - NULL -), -( - 'plural', - '(alias|canvas|status|campus)es$', - NULL -), -( - 'plural', - '^(summons|bonus)es$', - NULL -), -( - 'plural', - '^(ox)en', - NULL -), -( - 'plural', - '(matr)ices$', - NULL -), -( - 'plural', - '(vert|ind)ices$', - NULL -), -( - 'plural', - '^feet$', - NULL -), -( - 'plural', - '^teeth$', - NULL -), -( - 'plural', - '^geese$', - NULL -), -( - 'plural', - '(quiz)zes$', - NULL -), -( - 'plural', - '^(whereas)es$', - NULL -), -( - 'plural', - '^(criteri)a$', - NULL -), -( - 'plural', - '^genera$', - NULL -), -( - 'plural', - '^(m|wom)an$', - E'\\1en' -), -( - 'plural', - '(pe)rson$', - E'\\1ople' -), -( - 'plural', - '(child)$', - E'\\1ren' -), -( - 'plural', - '(drive)$', - E'\\1s' -), -( - 'plural', - '^(ox)$', - E'\\1en' -), -( - 'plural', - '(ax|test)is$', - E'\\1es' -), -( - 'plural', - '(octop|vir)us$', - E'\\1uses' -), -( - 'plural', - '(alias|status|canvas|campus)$', - E'\\1es' -), -( - 'plural', - '^(summons|bonus)$', - E'\\1es' -), -( - 'plural', - '(bu)s$', - E'\\1ses' -), -( - 'plural', - '(buffal|tomat|potat)o$', - E'\\1oes' -), -( - 'plural', - '([ti])um$', - E'\\1a' -), -( - 'plural', - 'sis$', - 'ses' -), -( - 'plural', - '(?:([^f])fe|([lr])f)$', - E'\\1\\2ves' -), -( - 'plural', - '^(focus)$', - E'\\1es' -), -( - 'plural', - '(hi|ti)ve$', - E'\\1ves' -), -( - 'plural', - '([^aeiouy]|qu)y$', - E'\\1ies' -), -( - 'plural', - '(matr)ix$', - E'\\1ices' -), -( - 'plural', - '(vert|ind)ex$', - E'\\1ices' -), -( - 'plural', - '(x|ch|ss|sh)$', - E'\\1es' -), -( - 'plural', - '([m|l])ouse$', - E'\\1ice' -), -( - 'plural', - '^foot$', - 'feet' -), -( - 'plural', - '^tooth$', - 'teeth' -), -( - 'plural', - '^goose$', - 'geese' -), -( - 'plural', - '(quiz)$', - E'\\1zes' -), -( - 'plural', - '^(whereas)$', - E'\\1es' -), -( - 'plural', - '^(criteri)on$', - E'\\1a' -), -( - 'plural', - '^genus$', - 'genera' -), -( - 'plural', - 's$', - 's' -), -( - 'plural', - '$', - 's' -), -( - 'singular', - '^(m|wom)an$', - NULL -), -( - 'singular', - '(pe)rson$', - NULL -), -( - 'singular', - '(child)$', - NULL -), -( - 'singular', - '(drive)$', - NULL -), -( - 'singular', - '^(ox)$', - NULL -), -( - 'singular', - '(ax|test)is$', - NULL -), -( - 'singular', - '(octop|vir)us$', - NULL -), -( - 'singular', - '(alias|status|canvas|campus)$', - NULL -), -( - 'singular', - '^(summons|bonus)$', - NULL -), -( - 'singular', - '(bu)s$', - NULL -), -( - 'singular', - '(buffal|tomat|potat)o$', - NULL -), -( - 'singular', - '([ti])um$', - NULL -), -( - 'singular', - 'sis$', - NULL -), -( - 'singular', - '(?:([^f])fe|([lr])f)$', - NULL -), -( - 'singular', - '^(focus)$', - NULL -), -( - 'singular', - '(hi|ti)ve$', - NULL -), -( - 'singular', - '([^aeiouy]|qu)y$', - NULL -), -( - 'singular', - '(x|ch|ss|sh)$', - NULL -), -( - 'singular', - '(matr)ix$', - NULL -), -( - 'singular', - '(vert|ind)ex$', - NULL -), -( - 'singular', - '([m|l])ouse$', - NULL -), -( - 'singular', - '^foot$', - NULL -), -( - 'singular', - '^tooth$', - NULL -), -( - 'singular', - '^goose$', - NULL -), -( - 'singular', - '(quiz)$', - NULL -), -( - 'singular', - '^(whereas)$', - NULL -), -( - 'singular', - '^(criteri)on$', - NULL -), -( - 'singular', - '^genus$', - NULL -), -( - 'singular', - '^(m|wom)en$', - E'\\1an' -), -( - 'singular', - '(pe)ople$', - E'\\1rson' -), -( - 'singular', - '(child)ren$', - E'\\1' -), -( - 'singular', - '(database)s$', - E'\\1' -), -( - 'singular', - '(drive)s$', - E'\\1' -), -( - 'singular', - '^genera$', - 'genus' -), -( - 'singular', - '^(criteri)a$', - E'\\1on' -), -( - 'singular', - '(schema)ta$', - E'\\1' -), -( - 'singular', - '(phenomen)a$', - E'\\1on' -), -( - 'singular', - '(memorand)a$', - E'\\1um' -), -( - 'singular', - '(curricul)a$', - E'\\1um' -), -( - 'singular', - '([ti])a$', - E'\\1um' -), -( - 'singular', - '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$', - E'\\1\\2sis' -), -( - 'singular', - '(hi|ti)ves$', - E'\\1ve' -), -( - 'singular', - '(curve)s$', - E'\\1' -), -( - 'singular', - '([lr])ves$', - E'\\1f' -), -( - 'singular', - '([a])ves$', - E'\\1ve' -), -( - 'singular', - '([^fo])ves$', - E'\\1fe' -), -( - 'singular', - '(m)ovies$', - E'\\1ovie' -), -( - 'singular', - '([^aeiouy]|qu)ies$', - E'\\1y' -), -( - 'singular', - '(s)eries$', - E'\\1eries' -), -( - 'singular', - '(x|ch|ss|sh)es$', - E'\\1' -), -( - 'singular', - '([m|l])ice$', - E'\\1ouse' -), -( - 'singular', - '(bus)es$', - E'\\1' -), -( - 'singular', - '(o)es$', - E'\\1' -), -( - 'singular', - '(shoe)s$', - E'\\1' -), -( - 'singular', - '(cris|ax|test)es$', - E'\\1is' -), -( - 'singular', - '(octop|vir)uses$', - E'\\1us' -), -( - 'singular', - '(alias|canvas|status|campus)es$', - E'\\1' -), -( - 'singular', - '^(summons|bonus)es$', - E'\\1' -), -( - 'singular', - '^(ox)en', - E'\\1' -), -( - 'singular', - '(matr)ices$', - E'\\1ix' -), -( - 'singular', - '(vert|ind)ices$', - E'\\1ex' -), -( - 'singular', - '^feet$', - 'foot' + ('plural', '^(m|wom)en$', NULL), + ('plural', '(pe)ople$', NULL), + ('plural', '(child)ren$', NULL), + ('plural', '([ti])a$', NULL), + ('plural', '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$', NULL), + ('plural', '(.+base)s$', NULL), + ('plural', '(database)s$', NULL), + ('plural', '(drive)s$', NULL), + ('plural', '(hi|ti)ves$', NULL), + ('plural', '(curve)s$', NULL), + ('plural', '([lr])ves$', NULL), + ('plural', '([^fo])ves$', NULL), + ('plural', '([^aeiouy]|qu)ies$', NULL), + ('plural', '(s)eries$', NULL), + ('plural', '(m)ovies$', NULL), + ('plural', '(x|ch|ss|sh)es$', NULL), + ('plural', '([m|l])ice$', NULL), + ('plural', '(bus)es$', NULL), + ('plural', '(o)es$', NULL), + ('plural', '(shoe)s$', NULL), + ('plural', '(cris|ax|test)es$', NULL), + ('plural', '(octop|vir)uses$', NULL), + ('plural', '(alias|canvas|status|campus)es$', NULL), + ('plural', '^(summons|bonus)es$', NULL), + ('plural', '^(ox)en', NULL), + ('plural', '(matr)ices$', NULL), + ('plural', '(vert|ind)ices$', NULL), + ('plural', '^feet$', NULL), + ('plural', '^teeth$', NULL), + ('plural', '^geese$', NULL), + ('plural', '(quiz)zes$', NULL), + ('plural', '^(whereas)es$', NULL), + ('plural', '^(criteri)a$', NULL), + ('plural', '^genera$', NULL), + ('plural', '^(m|wom)an$', E'\\1en'), + ('plural', '(pe)rson$', E'\\1ople'), + ('plural', '(child)$', E'\\1ren'), + ('plural', '(drive)$', E'\\1s'), + ('plural', '^(ox)$', E'\\1en'), + ('plural', '(ax|test)is$', E'\\1es'), + ('plural', '(octop|vir)us$', E'\\1uses'), + ('plural', '(alias|status|canvas|campus)$', E'\\1es'), + ('plural', '^(summons|bonus)$', E'\\1es'), + ('plural', '(bu)s$', E'\\1ses'), + ('plural', '(buffal|tomat|potat)o$', E'\\1oes'), + ('plural', '([ti])um$', E'\\1a'), + ('plural', 'sis$', 'ses'), + ('plural', '(?:([^f])fe|([lr])f)$', E'\\1\\2ves'), + ('plural', '^(focus)$', E'\\1es'), + ('plural', '(hi|ti)ve$', E'\\1ves'), + ('plural', '([^aeiouy]|qu)y$', E'\\1ies'), + ('plural', '(matr)ix$', E'\\1ices'), + ('plural', '(vert|ind)ex$', E'\\1ices'), + ('plural', '(x|ch|ss|sh)$', E'\\1es'), + ('plural', '([m|l])ouse$', E'\\1ice'), + ('plural', '^foot$', 'feet'), + ('plural', '^tooth$', 'teeth'), + ('plural', '^goose$', 'geese'), + ('plural', '(quiz)$', E'\\1zes'), + ('plural', '^(whereas)$', E'\\1es'), + ('plural', '^(criteri)on$', E'\\1a'), + ('plural', '^genus$', 'genera'), + ('plural', 's$', 's'), + ('plural', '$', 's'), + ('singular', '^(m|wom)an$', NULL), + ('singular', '(pe)rson$', NULL), + ('singular', '(child)$', NULL), + ('singular', '(drive)$', NULL), + ('singular', '^(ox)$', NULL), + ('singular', '(ax|test)is$', NULL), + ('singular', '(octop|vir)us$', NULL), + ('singular', '(alias|status|canvas|campus)$', NULL), + ('singular', '^(summons|bonus)$', NULL), + ('singular', '(bu)s$', NULL), + ('singular', '(buffal|tomat|potat)o$', NULL), + ('singular', '([ti])um$', NULL), + ('singular', 'sis$', NULL), + ('singular', '(?:([^f])fe|([lr])f)$', NULL), + ('singular', '^(focus)$', NULL), + ('singular', '(hi|ti)ve$', NULL), + ('singular', '([^aeiouy]|qu)y$', NULL), + ('singular', '(x|ch|ss|sh)$', NULL), + ('singular', '(matr)ix$', NULL), + ('singular', '(vert|ind)ex$', NULL), + ('singular', '([m|l])ouse$', NULL), + ('singular', '^foot$', NULL), + ('singular', '^tooth$', NULL), + ('singular', '^goose$', NULL), + ('singular', '(quiz)$', NULL), + ('singular', '^(whereas)$', NULL), + ('singular', '^(criteri)on$', NULL), + ('singular', '^genus$', NULL), + ('singular', '^(m|wom)en$', E'\\1an'), + ('singular', '(pe)ople$', E'\\1rson'), + ('singular', '(child)ren$', E'\\1'), + ('singular', '(database)s$', E'\\1'), + ('singular', '(drive)s$', E'\\1'), + ('singular', '^genera$', 'genus'), + ('singular', '^(criteri)a$', E'\\1on'), + ('singular', '(schema)ta$', E'\\1'), + ('singular', '(phenomen)a$', E'\\1on'), + ('singular', '(memorand)a$', E'\\1um'), + ('singular', '(curricul)a$', E'\\1um'), + ('singular', '([ti])a$', E'\\1um'), + ('singular', '(.+base)s$', E'\\1'), + ('singular', '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$', E'\\1\\2sis'), + ('singular', '(hi|ti)ves$', E'\\1ve'), + ('singular', '(curve)s$', E'\\1'), + ('singular', '([lr])ves$', E'\\1f'), + ('singular', '([a])ves$', E'\\1ve'), + ('singular', '([^fo])ves$', E'\\1fe'), + ('singular', '(m)ovies$', E'\\1ovie'), + ('singular', '([^aeiouy]|qu)ies$', E'\\1y'), + ('singular', '(s)eries$', E'\\1eries'), + ('singular', '(x|ch|ss|sh)es$', E'\\1'), + ('singular', '([m|l])ice$', E'\\1ouse'), + ('singular', '(bus)es$', E'\\1'), + ('singular', '(o)es$', E'\\1'), + ('singular', '(shoe)s$', E'\\1'), + ('singular', '(cris|ax|test)es$', E'\\1is'), + ('singular', '(octop|vir)uses$', E'\\1us'), + ('singular', '(alias|canvas|status|campus)es$', E'\\1'), + ('singular', '^(summons|bonus)es$', E'\\1'), + ('singular', '^(ox)en', E'\\1'), + ('singular', '(matr)ices$', E'\\1ix'), + ('singular', '(vert|ind)ices$', E'\\1ex'), + ('singular', '^feet$', 'foot'), + ('singular', '^teeth$', 'tooth'), + ('singular', '^geese$', 'goose'), + ('singular', '(quiz)zes$', E'\\1'), + ('singular', '^(whereas)es$', E'\\1'), + ('singular', 'ss$', 'ss'), + ('singular', 's$', ''); + +CREATE INDEX inflection_rules_type_idx ON inflection.inflection_rules (type); + +CREATE FUNCTION inflection.dns_1123( + value text +) RETURNS text AS $EOFCODE$ + WITH lowercased AS ( + SELECT + lower(value) AS value ), -( - 'singular', - '^teeth$', - 'tooth' +-- ':' delimits namespaced identifiers; map to '--' so the boundary survives +namespaced AS ( + SELECT + replace(value, ':', '--') AS value +FROM + lowercased ), -( - 'singular', - '^geese$', - 'goose' +hyphenated AS ( + SELECT + replace(value, '_', '-') AS value +FROM + namespaced ), -( - 'singular', - '(quiz)zes$', - E'\\1' +stripped AS ( + SELECT + regexp_replace(value, '[^a-z0-9-]', '', 'g') AS value +FROM + hyphenated ), -( - 'singular', - '^(whereas)es$', - E'\\1' +trimmed AS ( + SELECT + regexp_replace(value, '^-+|-+$', '', 'g') AS value +FROM + stripped ), -( - 'singular', - 'ss$', - 'ss' +truncated AS ( + SELECT + "left"(value, 63) AS value +FROM + trimmed ), -( - 'singular', - 's$', - '' -); - -CREATE INDEX inflection_rules_type_idx ON inflection.inflection_rules (type); \ No newline at end of file +-- truncation can leave a dangling '-'; drop any trailing non-alphanumerics +final AS ( + SELECT + regexp_replace(value, '[^a-z0-9]+$', '') AS value +FROM + truncated +) +SELECT + value +FROM + final; +$EOFCODE$ LANGUAGE sql STRICT IMMUTABLE; \ No newline at end of file diff --git a/packages/inflection/verify/schemas/inflection/procedures/dns_1123.sql b/packages/inflection/verify/schemas/inflection/procedures/dns_1123.sql new file mode 100644 index 00000000..6a0007af --- /dev/null +++ b/packages/inflection/verify/schemas/inflection/procedures/dns_1123.sql @@ -0,0 +1,7 @@ +-- Verify schemas/inflection/procedures/dns_1123 on pg + +BEGIN; + +SELECT verify_function ('inflection.dns_1123'); + +ROLLBACK;