From 6bfc73cc73a72f77e25d4ab9c2871036c8363db9 Mon Sep 17 00:00:00 2001 From: Sri-Mounika-Gopisetti Date: Tue, 9 Dec 2025 14:44:16 +0530 Subject: [PATCH 1/4] Add SQL parser to extract table names and column definitions --- src/language/sql/document.ts | 341 ++++++++++++++++++++++++++++------- 1 file changed, 277 insertions(+), 64 deletions(-) diff --git a/src/language/sql/document.ts b/src/language/sql/document.ts index 030c6e19..fcc6c462 100644 --- a/src/language/sql/document.ts +++ b/src/language/sql/document.ts @@ -1,6 +1,22 @@ import Statement from "./statement"; import SQLTokeniser from "./tokens"; -import { CallableReference, Definition, IRange, ParsedEmbeddedStatement, StatementGroup, StatementType, StatementTypeWord, Token } from "./types"; +import { Definition, ParsedEmbeddedStatement, StatementGroup, StatementType, StatementTypeWord, Token } from "./types"; + +export interface ParsedColumn { + columnName: string; + aliasName?: string; + isAlias: boolean; + type?: string; +} + +export interface ParsedTableEntry { + tableName: string; + systemTableName?:string; + columns: ParsedColumn[]; // array of columns for that table +} +export interface ParsedTable { + columns: ParsedColumn[]; +} export default class Document { content: string; @@ -130,28 +146,21 @@ export default class Document { getStatementGroups(): StatementGroup[] { let groups: StatementGroup[] = []; - let currentGroup: Statement[] = []; - let depth = 0; - for (const statement of this.statements) { if (statement.isCompoundEnd()) { if (depth > 0) { - currentGroup.push(statement); - + currentGroup.push(statement); depth--; - this.log(`<` + ``.padEnd(depth*2) + Statement.formatSimpleTokens(statement.tokens.slice(0, 2))); } - if (depth === 0) { if (currentGroup.length > 0) { groups.push({ range: { start: currentGroup[0].range.start, end: currentGroup[currentGroup.length-1].range.end }, statements: currentGroup }); - currentGroup = []; } } @@ -163,9 +172,7 @@ export default class Document { } else { currentGroup = [statement]; } - depth++; - } else { this.log(` ` + ``.padEnd(depth*2) + Statement.formatSimpleTokens(statement.tokens.slice(0, 2))); if (depth > 0) { @@ -188,6 +195,21 @@ export default class Document { return groups; } + getColumnsAndTable():ParsedTableEntry[] { + const groups = this.getStatementGroups(); + + const result:ParsedTableEntry[] = []; + + for (const group of groups) { + if(group.statements[0].type === StatementType.Create) { + const info:ParsedTableEntry = getCreateTableInfo(group.statements[0].tokens); + result.push(info); + + } + } + + return result; + } getDefinitions(): Definition[] { const groups = this.getStatementGroups(); @@ -223,7 +245,7 @@ export default class Document { }) } - removeEmbeddedAreas(statement: Statement, options: {replacement: `snippet`|`?`|`values`, values?: any[]} = {replacement: `?`}): ParsedEmbeddedStatement { + removeEmbeddedAreas(statement: Statement, snippetString?: boolean): ParsedEmbeddedStatement { const areas = statement.getEmbeddedStatementAreas(); const totalParameters = areas.filter(a => a.type === `marker`).length; @@ -242,73 +264,25 @@ export default class Document { case `marker`: const markerContent = newContent.substring(start, end); - switch (options.replacement) { - case `snippet`: - newContent = newContent.substring(0, start) + `\${${totalParameters-parameterCount}:${markerContent}}` + newContent.substring(end) + `$0`; - break; - case `?`: - newContent = newContent.substring(0, start) + `?` + newContent.substring(end); - break; - case `values`: - let valueIndex = totalParameters - parameterCount - 1; - if (options.values && options.values.length > valueIndex) { - let value = options.values[valueIndex]; - - if (typeof value === `string`) { - value = `'${value.replace(/'/g, `''`)}'`; // Escape single quotes in strings - } - - newContent = newContent.substring(0, start) + value + newContent.substring(end); - } else { - newContent = newContent.substring(0, start) + `?` + newContent.substring(end); - } - break; - } + newContent = newContent.substring(0, start) + (snippetString ? `\${${totalParameters-parameterCount}:${markerContent}}` : `?`) + newContent.substring(end) + (snippetString ? `$0` : ``); parameterCount++; break; case `remove`: - newContent = newContent.substring(0, start) + newContent.substring(end); - if (newContent[start-1] === ` ` && newContent[start] === ` `) { - newContent = newContent.substring(0, start-1) + newContent.substring(start); - } + newContent = newContent.substring(0, start) + newContent.substring(end+1); break; } } return { changed: areas.length > 0, - content: newContent.trim(), + content: newContent, parameterCount }; } } - -export function getPositionData(ref: CallableReference, offset: number) { - const paramCommas = ref.tokens.filter(token => token.type === `comma`); - - let currentParm = paramCommas.findIndex(t => offset < t.range.start); - - if (currentParm === -1) { - currentParm = paramCommas.length; - } - - const firstNamedPipe = ref.tokens.find((token, i) => token.type === `rightpipe`); - let firstNamedParameter = firstNamedPipe ? paramCommas.findIndex((token, i) => token.range.start > firstNamedPipe.range.start) : undefined; - - if (firstNamedParameter === -1) { - firstNamedParameter = undefined; - } - - return { - currentParm, - currentCount: paramCommas.length + 1, - firstNamedParameter - }; -} - function getSymbolsForStatements(statements: Statement[]) { let defintions: Definition[] = []; @@ -331,4 +305,243 @@ function getSymbolsForStatements(statements: Statement[]) { } return defintions; -} \ No newline at end of file +} + + +//----------------------------------------------------------- +// UNIVERSAL SQL COLUMN PARSER FOR ALL CREATE TABLE STYLES +//----------------------------------------------------------- +//----------------------------------------------------------- +// UNIVERSAL SQL PARSER (TABLE NAME + COLUMNS) +//----------------------------------------------------------- +export function getCreateTableInfo(tokens: any[]):ParsedTableEntry { + const {tableName,systemName} = extractTableNames(tokens); + const columnGroups = extractColumnGroups(tokens); + const columnsValues = extractColumnNames(columnGroups); + const {columns,ColumnNames}= columnsValues; + return { + tableName: tableName, + systemTableName:systemName ?? tableName, + columns: ColumnNames + }; +} + +//----------------------------------------------------------- +// 0) Extract TABLE NAME from CREATE TABLE statement +//----------------------------------------------------------- +function extractTableNames(tokens: any[]) { + let foundTable = false; + let tableNameParts: string[] = []; + let systemName: string | null = null; + + for (let i = 0; i < tokens.length; i++) { + const v = tokens[i].value?.toLowerCase(); + + // Detect TABLE keyword + if (v === "table") { + foundTable = true; + continue; + } + + if (!foundTable) continue; + + // STOP collecting table name if "(" begins + if (tokens[i].value === "(") break; + + // Detect "FOR SYSTEM NAME " + if ( + v === "for" && + tokens[i + 1]?.value?.toLowerCase() === "system" && + tokens[i + 2]?.value?.toLowerCase() === "name" + ) { + // system name is the next token after NAME + systemName = tokens[i + 3]?.value ?? null; + break; // STOP reading table name + } + + // Skip noise keywords + const skip = ["if", "not", "exists", "or", "replace"]; + if (skip.includes(v)) continue; + + // Collect table name parts + if ( + tokens[i].type === "word" || + tokens[i].type === "string" || + /[\/\.]/.test(tokens[i].value) + ) { + tableNameParts.push(tokens[i].value); + } + } + + const tableName = tableNameParts.length > 0 ? tableNameParts.join("") : null; + + return { tableName, systemName }; +} + + + + +//----------------------------------------------------------- +// 1) Extract column groups inside the main ( ... ) block +//----------------------------------------------------------- +function extractColumnGroups(tokens: any[]) { + let startIndex = -1; + let depth = 0; + for (let i = 0; i < tokens.length; i++) { + const t = tokens[i]; + + if (t.value === "(" && startIndex === -1) { + startIndex = i; + depth = 1; + i++; + + // find matching closing ) + while (i < tokens.length && depth > 0) { + if (tokens[i].value === "(") depth++; + else if (tokens[i].value === ")") depth--; + i++; + } + + const endIndex = i - 1; + const innerTokens = tokens.slice(startIndex + 1, endIndex); + + // --------------------------------------------------- + // Split by commas ONLY on depth=0 + // --------------------------------------------------- + const groups: any[][] = []; + let current: any[] = []; + let d = 0; + + for (const token of innerTokens) { + if (token.value === "," && d === 0) { + if (current.length > 0) { + groups.push(current); + current = []; + } + continue; + } + + current.push(token); + + if (token.value === "(") d++; + else if (token.value === ")") d--; + } + + if (current.length > 0) groups.push(current); + + // REMOVE TABLE CONSTRAINT GROUPS + const unwanted = [ + "constraint", + "primary", + "foreign", + "unique", + "check", + "references", + "key" + ]; + + return groups.filter(group => { + const text = group.map(t => t.value.toLowerCase()).join(" "); + return !unwanted.some(word => text.startsWith(word)); + }); + } + } + + return []; +} + +//----------------------------------------------------------- +// 2) Extract column names from each group +//----------------------------------------------------------- + + + +function extractColumnNames(groups: any[][]) { + const columns: string[] = []; + const ColumnNames: ParsedColumn[] = []; + + + for (const group of groups) { + const result = parseSingleColumn(group); + if (!result) continue; + + const { aliasForColumn, normalIdentifiers } = result; +if(aliasForColumn.length===1&& normalIdentifiers.length===1) +{ + ColumnNames.push({columnName:normalIdentifiers[0], aliasName:aliasForColumn[0], isAlias: true}); + ColumnNames.push({columnName:aliasForColumn[0], isAlias: false}); + ColumnNames.map(col=> columns.push(col.columnName)); + // columns.push(columnNames); + // +} + } + + return {columns, + ColumnNames + }; +} + + +//----------------------------------------------------------- +// 3) Parse a single column definition +//----------------------------------------------------------- +function parseSingleColumn(tokens: any[]) { + if (!tokens.length) return null; + + const aliasForColumn: string[] = []; + const normalIdentifiers: string[] = []; + + // ---------------------------------------------- + // A) FIRST TOKEN CHECK → Alias name (only once) + // ---------------------------------------------- + const first = tokens[0]; + if (first && first.type === "word" && !isKeyword(first.value)) { + aliasForColumn.push(cleanIdentifier(first.value)); + } + + // ---------------------------------------------- + // B) Look for "FOR COLUMN realColumn" + // ---------------------------------------------- + for (let i = 0; i < tokens.length; i++) { + const t = tokens[i].value?.toLowerCase(); + + if ( + t === "for" && + tokens[i + 1]?.value?.toLowerCase() === "column" && + tokens[i + 2] + ) { + normalIdentifiers.push(cleanIdentifier(tokens[i + 2].value)); + } + } + + // ---------------------------------------------- + // C) Return final structured result + // ---------------------------------------------- + return { + aliasForColumn, + normalIdentifiers, + }; +} + + +//----------------------------------------------------------- +// Helpers +//----------------------------------------------------------- + + +function cleanIdentifier(name: string) { + return name.replace(/^[`\["']+|[`"\]']+$/g, ""); +} + +function isKeyword(val: string) { + const keywords = [ + "char", "varchar", "nvarchar", "text", "int", "integer", "bigint", + "decimal", "numeric", "float", "real", "double", + "date", "datetime", "timestamp", "time", + "ccsid", "default", "constraint", "primary", "foreign", + "key", "unique", "check", "not", "null", "for", "column", + "references", "on", "update", "delete", "by" + ]; + + return keywords.includes(val.toLowerCase()); +} From 09859c64037992c4a5c90fa7a93027d4b8f6bea0 Mon Sep 17 00:00:00 2001 From: Sri-Mounika-Gopisetti Date: Tue, 9 Dec 2025 15:10:44 +0530 Subject: [PATCH 2/4] some chnages --- src/language/sql/document.ts | 135 ++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/src/language/sql/document.ts b/src/language/sql/document.ts index fcc6c462..5bc7de23 100644 --- a/src/language/sql/document.ts +++ b/src/language/sql/document.ts @@ -1,23 +1,24 @@ import Statement from "./statement"; import SQLTokeniser from "./tokens"; -import { Definition, ParsedEmbeddedStatement, StatementGroup, StatementType, StatementTypeWord, Token } from "./types"; +import { CallableReference, Definition, IRange, ParsedEmbeddedStatement, StatementGroup, StatementType, StatementTypeWord, Token } from "./types"; + + export interface ParsedColumn { - columnName: string; - aliasName?: string; - isAlias: boolean; - type?: string; + columnName: string; // SQL-facing or physical name + aliasName?: string; // always the real DB2 column name (zztype, zzvaleur, etc.) + isAlias: boolean; // true if alias name, false if physical name + type?: string; // optional: char(5), varchar(20), etc. } export interface ParsedTableEntry { tableName: string; - systemTableName?:string; + systemTableName?:string; // "mouni", "mouni3", "mylib/zz01pf", etc. columns: ParsedColumn[]; // array of columns for that table } export interface ParsedTable { columns: ParsedColumn[]; } - export default class Document { content: string; statements: Statement[]; @@ -146,21 +147,28 @@ export default class Document { getStatementGroups(): StatementGroup[] { let groups: StatementGroup[] = []; + let currentGroup: Statement[] = []; + let depth = 0; + for (const statement of this.statements) { if (statement.isCompoundEnd()) { if (depth > 0) { - currentGroup.push(statement); + currentGroup.push(statement); + depth--; + this.log(`<` + ``.padEnd(depth*2) + Statement.formatSimpleTokens(statement.tokens.slice(0, 2))); } + if (depth === 0) { if (currentGroup.length > 0) { groups.push({ range: { start: currentGroup[0].range.start, end: currentGroup[currentGroup.length-1].range.end }, statements: currentGroup }); + currentGroup = []; } } @@ -172,7 +180,9 @@ export default class Document { } else { currentGroup = [statement]; } + depth++; + } else { this.log(` ` + ``.padEnd(depth*2) + Statement.formatSimpleTokens(statement.tokens.slice(0, 2))); if (depth > 0) { @@ -245,7 +255,7 @@ export default class Document { }) } - removeEmbeddedAreas(statement: Statement, snippetString?: boolean): ParsedEmbeddedStatement { + removeEmbeddedAreas(statement: Statement, options: {replacement: `snippet`|`?`|`values`, values?: any[]} = {replacement: `?`}): ParsedEmbeddedStatement { const areas = statement.getEmbeddedStatementAreas(); const totalParameters = areas.filter(a => a.type === `marker`).length; @@ -264,25 +274,73 @@ export default class Document { case `marker`: const markerContent = newContent.substring(start, end); - newContent = newContent.substring(0, start) + (snippetString ? `\${${totalParameters-parameterCount}:${markerContent}}` : `?`) + newContent.substring(end) + (snippetString ? `$0` : ``); + switch (options.replacement) { + case `snippet`: + newContent = newContent.substring(0, start) + `\${${totalParameters-parameterCount}:${markerContent}}` + newContent.substring(end) + `$0`; + break; + case `?`: + newContent = newContent.substring(0, start) + `?` + newContent.substring(end); + break; + case `values`: + let valueIndex = totalParameters - parameterCount - 1; + if (options.values && options.values.length > valueIndex) { + let value = options.values[valueIndex]; + + if (typeof value === `string`) { + value = `'${value.replace(/'/g, `''`)}'`; // Escape single quotes in strings + } + + newContent = newContent.substring(0, start) + value + newContent.substring(end); + } else { + newContent = newContent.substring(0, start) + `?` + newContent.substring(end); + } + break; + } parameterCount++; break; case `remove`: - newContent = newContent.substring(0, start) + newContent.substring(end+1); + newContent = newContent.substring(0, start) + newContent.substring(end); + if (newContent[start-1] === ` ` && newContent[start] === ` `) { + newContent = newContent.substring(0, start-1) + newContent.substring(start); + } break; } } return { changed: areas.length > 0, - content: newContent, + content: newContent.trim(), parameterCount }; } } + +export function getPositionData(ref: CallableReference, offset: number) { + const paramCommas = ref.tokens.filter(token => token.type === `comma`); + + let currentParm = paramCommas.findIndex(t => offset < t.range.start); + + if (currentParm === -1) { + currentParm = paramCommas.length; + } + + const firstNamedPipe = ref.tokens.find((token, i) => token.type === `rightpipe`); + let firstNamedParameter = firstNamedPipe ? paramCommas.findIndex((token, i) => token.range.start > firstNamedPipe.range.start) : undefined; + + if (firstNamedParameter === -1) { + firstNamedParameter = undefined; + } + + return { + currentParm, + currentCount: paramCommas.length + 1, + firstNamedParameter + }; +} + function getSymbolsForStatements(statements: Statement[]) { let defintions: Definition[] = []; @@ -491,57 +549,38 @@ function parseSingleColumn(tokens: any[]) { const aliasForColumn: string[] = []; const normalIdentifiers: string[] = []; - // ---------------------------------------------- - // A) FIRST TOKEN CHECK → Alias name (only once) - // ---------------------------------------------- - const first = tokens[0]; - if (first && first.type === "word" && !isKeyword(first.value)) { - aliasForColumn.push(cleanIdentifier(first.value)); - } - - // ---------------------------------------------- - // B) Look for "FOR COLUMN realColumn" - // ---------------------------------------------- + // ------------------------------- + // A) Collect DB2 alias-for-column + // ------------------------------- for (let i = 0; i < tokens.length; i++) { const t = tokens[i].value?.toLowerCase(); +// IF first token is identifier/word/string → it's the alias name + if(tokens[i].value===tokens[0].value && tokens[0].type==="word") + { + aliasForColumn.push(cleanIdentifier(tokens[0].value)); + } - if ( - t === "for" && - tokens[i + 1]?.value?.toLowerCase() === "column" && - tokens[i + 2] - ) { - normalIdentifiers.push(cleanIdentifier(tokens[i + 2].value)); + // IF (FOR COLUMN realName) + else if (t === "for" && tokens[i + 1]?.value?.toLowerCase() === "column") { + const real = tokens[i + 2]; + if (real) normalIdentifiers.push(cleanIdentifier(real.value)); } + } - // ---------------------------------------------- - // C) Return final structured result - // ---------------------------------------------- + // ------------------------ + // B) Return everything + // ------------------------ return { aliasForColumn, normalIdentifiers, }; } - //----------------------------------------------------------- // Helpers //----------------------------------------------------------- - function cleanIdentifier(name: string) { return name.replace(/^[`\["']+|[`"\]']+$/g, ""); -} - -function isKeyword(val: string) { - const keywords = [ - "char", "varchar", "nvarchar", "text", "int", "integer", "bigint", - "decimal", "numeric", "float", "real", "double", - "date", "datetime", "timestamp", "time", - "ccsid", "default", "constraint", "primary", "foreign", - "key", "unique", "check", "not", "null", "for", "column", - "references", "on", "update", "delete", "by" - ]; - - return keywords.includes(val.toLowerCase()); -} +} \ No newline at end of file From a105a908b03505f2cdc7ae11d342f513399dd1ee Mon Sep 17 00:00:00 2001 From: Sri-Mounika-Gopisetti Date: Thu, 11 Dec 2025 12:05:55 +0530 Subject: [PATCH 3/4] The blocks.test.ts file contains the test cases associated with the getColumnsAndTable function --- src/language/sql/document.ts | 58 +++++++++++++++++++++------ src/language/sql/tests/blocks.test.ts | 46 ++++++++++++++++++++- 2 files changed, 90 insertions(+), 14 deletions(-) diff --git a/src/language/sql/document.ts b/src/language/sql/document.ts index 5bc7de23..f8f5d6ce 100644 --- a/src/language/sql/document.ts +++ b/src/language/sql/document.ts @@ -499,8 +499,7 @@ function extractColumnGroups(tokens: any[]) { ]; return groups.filter(group => { - const text = group.map(t => t.value.toLowerCase()).join(" "); - return !unwanted.some(word => text.startsWith(word)); + return !unwanted.includes(group[0].value.toLowerCase()) }); } } @@ -522,16 +521,41 @@ function extractColumnNames(groups: any[][]) { for (const group of groups) { const result = parseSingleColumn(group); if (!result) continue; - const { aliasForColumn, normalIdentifiers } = result; -if(aliasForColumn.length===1&& normalIdentifiers.length===1) -{ - ColumnNames.push({columnName:normalIdentifiers[0], aliasName:aliasForColumn[0], isAlias: true}); - ColumnNames.push({columnName:aliasForColumn[0], isAlias: false}); - ColumnNames.map(col=> columns.push(col.columnName)); - // columns.push(columnNames); - // + let alias=normalizeNames(aliasForColumn); + let normal=normalizeNames(normalIdentifiers); + +if (alias.length === 1 && normal.length === 1) { + // Case 1: Both alias and real column exist + ColumnNames.push({ + columnName: normal[0], + aliasName: alias[0], + isAlias: true + }); + + ColumnNames.push({ + columnName: alias[0], + isAlias: false + }); +} +else if (alias.length === 1 && normal.length === 0) { + // Case 2: Only alias exists + ColumnNames.push({ + columnName: alias[0], + isAlias: false + }); } +else if (normal.length === 1 && alias.length === 0) { + // Case 3: Only real column name exists (rare case) + ColumnNames.push({ + columnName: normal[0], + isAlias: false + }); +} + +// Push to columns array +ColumnNames.forEach(col => columns.push(col.columnName)); + } return {columns, @@ -539,7 +563,15 @@ if(aliasForColumn.length===1&& normalIdentifiers.length===1) }; } +function normalizeNames(arr: string[]) { + // clean quotes + lowercase + const cleaned = arr.map(a => cleanIdentifier(a).toLowerCase()); + + // remove duplicates + const unique = [...new Set(cleaned)]; + return unique; // can be 1 or many +} //----------------------------------------------------------- // 3) Parse a single column definition //----------------------------------------------------------- @@ -554,13 +586,13 @@ function parseSingleColumn(tokens: any[]) { // ------------------------------- for (let i = 0; i < tokens.length; i++) { const t = tokens[i].value?.toLowerCase(); -// IF first token is identifier/word/string → it's the alias name - if(tokens[i].value===tokens[0].value && tokens[0].type==="word") + // IF first token is identifier/word/string/sqlName → it's the alias name and also considering the sqlName type with quotes + if(t===tokens[0].value.toLowerCase() && (tokens[0].type ==="word"||(tokens[0].type==="sqlName" && tokens[0].value.startsWith('"'))) ) { aliasForColumn.push(cleanIdentifier(tokens[0].value)); } - // IF (FOR COLUMN realName) + // IF (FOR COLUMN realName as per SYSTEM) else if (t === "for" && tokens[i + 1]?.value?.toLowerCase() === "column") { const real = tokens[i + 2]; if (real) normalIdentifiers.push(cleanIdentifier(real.value)); diff --git a/src/language/sql/tests/blocks.test.ts b/src/language/sql/tests/blocks.test.ts index 3b8cb6a2..d7c319d9 100644 --- a/src/language/sql/tests/blocks.test.ts +++ b/src/language/sql/tests/blocks.test.ts @@ -538,6 +538,9 @@ test('CREATE statements', () => { const doc = new Document(lines); const groups = doc.getStatementGroups(); + const TABLEandCOLUMNS = doc.getColumnsAndTable(); + expect(TABLEandCOLUMNS[0].tableName).toBe("temp_t1"); + expect(TABLEandCOLUMNS[0].columns.length).toBe(7); expect(groups.length).toBe(3); }); @@ -554,4 +557,45 @@ test(`ALTER with BEGIN`, () => { const doc = new Document(lines); const groups = doc.getStatementGroups(); expect(groups.length).toBe(1); -}) \ No newline at end of file +}) +// getTableandColumn +test(`Get table and column details from a CREATE statement that contains different column-name formats.`, () => { + const lines = [ + `CREATE OR REPLACE TABLE Schema1.ComplexTable (`, + + ` ID INT PRIMARY KEY,`, + + `"Full Name" VARCHAR(255) NOT NULL,`, + + `"select" VARCHAR(50),`, + `Age INT CHECK (Age > 0),`, + + `"Emp-Code" VARCHAR(40),`, + + `details JSON CHECK (JSON_VALID(details)),`, + + `Status ENUM('OPEN', 'CLOSED', 'IN_PROGRESS') DEFAULT 'OPEN',`, + + `WeirdColumn DECIMAL(10,2) DEFAULT 0.00,`, + + `Part1 INT,`, + `Part2 INT,`, + + `Salary DECIMAL(10,2),`, + + `DeptID INT,`, + + ` CONSTRAINT fk_dept FOREIGN KEY (DeptID) REFERENCES Departments(DeptID),`, + + `PRIMARY KEY (Part1, Part2),`, + + `UNIQUE ("Full Name")`, + + `);`, + ].join(`\n`); + const doc = new Document(lines); + const TABLEandCOLUMNS = doc.getColumnsAndTable(); + console.log(TABLEandCOLUMNS[0].columns); + expect(TABLEandCOLUMNS[0].tableName).toBe("Schema1.ComplexTable"); + expect(TABLEandCOLUMNS[0].columns.length).toBe(12); +}); From 5a6f1b7b3ef4a5ea9e8d55419a46b7d1fb980206 Mon Sep 17 00:00:00 2001 From: Sri-Mounika-Gopisetti Date: Thu, 11 Dec 2025 12:14:46 +0530 Subject: [PATCH 4/4] removing unwanted comments --- src/language/sql/document.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/language/sql/document.ts b/src/language/sql/document.ts index f8f5d6ce..041bd380 100644 --- a/src/language/sql/document.ts +++ b/src/language/sql/document.ts @@ -5,15 +5,15 @@ import { CallableReference, Definition, IRange, ParsedEmbeddedStatement, Stateme export interface ParsedColumn { - columnName: string; // SQL-facing or physical name - aliasName?: string; // always the real DB2 column name (zztype, zzvaleur, etc.) - isAlias: boolean; // true if alias name, false if physical name - type?: string; // optional: char(5), varchar(20), etc. + columnName: string; + aliasName?: string; + isAlias: boolean; + type?: string; } export interface ParsedTableEntry { tableName: string; - systemTableName?:string; // "mouni", "mouni3", "mylib/zz01pf", etc. + systemTableName?:string; columns: ParsedColumn[]; // array of columns for that table } export interface ParsedTable {