From 2b3f76f92e9477e42533477e7ac4affdecd2d30b Mon Sep 17 00:00:00 2001 From: aayushbh-google Date: Fri, 23 Oct 2026 21:48:44 +0000 Subject: [PATCH 1/2] Minor updates to BigQuery constraints. --- toolbox/mdcode/docs/semantic-model/osi-google-schema.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/toolbox/mdcode/docs/semantic-model/osi-google-schema.json b/toolbox/mdcode/docs/semantic-model/osi-google-schema.json index 212cb1c9..67b26f51 100644 --- a/toolbox/mdcode/docs/semantic-model/osi-google-schema.json +++ b/toolbox/mdcode/docs/semantic-model/osi-google-schema.json @@ -955,8 +955,9 @@ }, "FieldName": { "type": "string", - "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,299}$", - "description": "A field name. A BigQuery column name: a letter or underscore, then letters, digits or underscores, up to 300 characters." + "pattern": "^(`[^`]+`|[\\p{L}\\p{N}\\p{Pc}\\p{Pd}\\p{M}\\s&%=>+:'<#|]+)$", + "maxLength": 300, + "description": "A field name. A BigQuery flexible column name: can be a backtick-quoted string, or contain letters, numbers, marks, connectors, dashes, spaces, and specific symbols, up to 300 characters." }, "ProfileDocument": { "type": "object", From 5d76123ea9736a8498e2e8b389f6bb4e595eabff Mon Sep 17 00:00:00 2001 From: aayushbh-google Date: Sat, 24 Oct 2026 01:03:29 +0000 Subject: [PATCH 2/2] adding changes to names* file along with the test case updates. --- toolbox/mdcode/src/libts/semantic/names.ts | 6 ++-- .../mdcode/tests/libts/semantic/names.test.ts | 32 +++++++++++++++---- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/toolbox/mdcode/src/libts/semantic/names.ts b/toolbox/mdcode/src/libts/semantic/names.ts index da25ccca..5a97a412 100644 --- a/toolbox/mdcode/src/libts/semantic/names.ts +++ b/toolbox/mdcode/src/libts/semantic/names.ts @@ -37,9 +37,9 @@ const IN_SQL: NameRule = { max: 500, }; const FIELD: NameRule = { - pattern: /^[A-Za-z_][A-Za-z0-9_]*$/, - shown: '^[A-Za-z_][A-Za-z0-9_]{0,299}$', - says: 'a letter or underscore, then letters, digits or underscores', + pattern: /^(`[^`]+`|[\p{L}\p{N}\p{Pc}\p{Pd}\p{M}\s&%=>+:'<#|]+)$/u, + shown: "^(`[^`]+`|[\\p{L}\\p{N}\\p{Pc}\\p{Pd}\\p{M}\\s&%=>+:'<#|]+)$", + says: 'a BigQuery flexible column name', max: 300, }; diff --git a/toolbox/mdcode/tests/libts/semantic/names.test.ts b/toolbox/mdcode/tests/libts/semantic/names.test.ts index 70d5d073..efbfca14 100644 --- a/toolbox/mdcode/tests/libts/semantic/names.test.ts +++ b/toolbox/mdcode/tests/libts/semantic/names.test.ts @@ -11,7 +11,9 @@ const IN_SQL: NameKind[] = ['entity', 'metric', 'relationship']; describe('nameProblem', () => { test('each kind accepts a plain name and rejects a slash, a leading digit or a space', () => { - for (const kind of KINDS) { + // Field names are now more flexible, so we exclude them from the restrictive tests + const restrictiveKinds = KINDS.filter(k => k !== 'field'); + for (const kind of restrictiveKinds) { expect(nameProblem(kind, 'orders_2024')).toBeUndefined(); for (const bad of ['sales/orders', '2024_orders', 'order date', '*', 'prod,us', '']) { expect(nameProblem(kind, bad)).toContain(`name '${bad}' is not valid`); @@ -19,11 +21,28 @@ describe('nameProblem', () => { } }); - test('a hyphen is accepted in a model, profile or deployment name only', () => { + test('a field name accepts flexible BigQuery characters, spaces, and backtick-quoting', () => { + // Valid unquoted flexible names + expect(nameProblem('field', 'order date')).toBeUndefined(); + expect(nameProblem('field', '2024_orders')).toBeUndefined(); + expect(nameProblem('field', 'R&D cost')).toBeUndefined(); + expect(nameProblem('field', 'growth %')).toBeUndefined(); + + // Valid backtick-quoted names + expect(nameProblem('field', '`sales/orders!`')).toBeUndefined(); + expect(nameProblem('field', '`my*column`')).toBeUndefined(); + + // Invalid unquoted names + for (const bad of ['sales/orders', '*', 'my@column', '']) { + expect(nameProblem('field', bad)).toContain(`name '${bad}' is not valid`); + } + }); + + test('a hyphen is accepted in a model, field, profile or deployment name only', () => { for (const kind of WITH_HYPHEN) { expect(nameProblem(kind, 'sales-analytics')).toBeUndefined(); } - for (const kind of [...IN_SQL, 'field'] as NameKind[]) { + for (const kind of [...IN_SQL] as NameKind[]) { expect(nameProblem(kind, 'my-entity')).toContain(`name 'my-entity' is not valid`); } }); @@ -60,10 +79,9 @@ describe('nameProblem', () => { expect(nameProblem('model', 'sales/orders')).toBe( "Model name 'sales/orders' is not valid; names must match " + '^[A-Za-z][A-Za-z0-9_-]*$: a letter, then letters, digits, underscores or hyphens.'); - expect(nameProblem('field', 'order date')).toBe( - "Field name 'order date' is not valid; names must match " + - '^[A-Za-z_][A-Za-z0-9_]{0,299}$: a letter or underscore, then letters, digits or ' + - 'underscores.'); + expect(nameProblem('field', 'my@column')).toBe( + "Field name 'my@column' is not valid; names must match " + + "^(`[^`]+`|[\\p{L}\\p{N}\\p{Pc}\\p{Pd}\\p{M}\\s&%=>+:'<#|]+)$: a BigQuery flexible column name."); }); test('a catalog entry description holds 2,000 characters', () => {