Shorten identifiers

This commit is contained in:
SPRINX0\prochazka
2025-09-25 10:38:14 +02:00
parent 9d77cac4bb
commit 78026f7fa5
7 changed files with 35 additions and 13 deletions

View File

@@ -366,8 +366,6 @@ async function handleSaveTableData({ msgid, changeSet }) {
errorMessage: extractErrorMessage(err, 'Error executing SQL script'), errorMessage: extractErrorMessage(err, 'Error executing SQL script'),
}); });
} }
} }
async function handleSqlPreview({ msgid, objects, options }) { async function handleSqlPreview({ msgid, objects, options }) {

View File

@@ -13,7 +13,7 @@ import type {
FilterBehaviour, FilterBehaviour,
} from 'dbgate-types'; } from 'dbgate-types';
import { parseFilter } from 'dbgate-filterparser'; import { parseFilter } from 'dbgate-filterparser';
import { filterName } from 'dbgate-tools'; import { filterName, shortenIdentifier } from 'dbgate-tools';
import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet'; import { ChangeSetFieldDefinition, ChangeSetRowDefinition } from './ChangeSet';
import { Expression, Select, treeToSql, dumpSqlSelect, Condition, CompoudCondition } from 'dbgate-sqltree'; import { Expression, Select, treeToSql, dumpSqlSelect, Condition, CompoudCondition } from 'dbgate-sqltree';
import { isTypeLogical, standardFilterBehaviours, detectSqlFilterBehaviour, stringFilterBehaviour } from 'dbgate-tools'; import { isTypeLogical, standardFilterBehaviours, detectSqlFilterBehaviour, stringFilterBehaviour } from 'dbgate-tools';
@@ -606,7 +606,9 @@ export abstract class GridDisplay {
} }
return { return {
exprType: 'column', exprType: 'column',
...(!this.dialect.omitTableAliases && { alias: alias || col.columnName }), ...(!this.dialect.omitTableAliases && {
alias: alias ? shortenIdentifier(alias, this.driver.dialect.maxIdentifierLength) : col.columnName,
}),
source, source,
...col, ...col,
}; };

View File

@@ -1,5 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
import { filterName, isTableColumnUnique } from 'dbgate-tools'; import { filterName, isTableColumnUnique, shortenIdentifier } from 'dbgate-tools';
import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay'; import { GridDisplay, ChangeCacheFunc, DisplayColumn, DisplayedColumnInfo, ChangeConfigFunc } from './GridDisplay';
import type { import type {
TableInfo, TableInfo,
@@ -101,8 +101,8 @@ export class TableGridDisplay extends GridDisplay {
...col, ...col,
isChecked: this.isColumnChecked(col), isChecked: this.isColumnChecked(col),
hintColumnNames: hintColumnNames:
this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map( this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map(columnName =>
columnName => `hint_${col.uniqueName}_${columnName}` shortenIdentifier(`hint_${col.uniqueName}_${columnName}`, this.driver.dialect.maxIdentifierLength)
) || null, ) || null,
hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null) hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)
?.delimiter, ?.delimiter,
@@ -116,7 +116,7 @@ export class TableGridDisplay extends GridDisplay {
if (this.isExpandedColumn(column.uniqueName)) { if (this.isExpandedColumn(column.uniqueName)) {
const table = this.getFkTarget(column); const table = this.getFkTarget(column);
if (table) { if (table) {
const childAlias = `${column.uniqueName}_ref`; const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
const subcolumns = this.getDisplayColumns(table, column.uniquePath); const subcolumns = this.getDisplayColumns(table, column.uniquePath);
this.addReferenceToSelect(select, parentAlias, column); this.addReferenceToSelect(select, parentAlias, column);
@@ -129,7 +129,7 @@ export class TableGridDisplay extends GridDisplay {
} }
addReferenceToSelect(select: Select, parentAlias: string, column: DisplayColumn) { addReferenceToSelect(select: Select, parentAlias: string, column: DisplayColumn) {
const childAlias = `${column.uniqueName}_ref`; const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
if ((select.from.relations || []).find(x => x.alias == childAlias)) return; if ((select.from.relations || []).find(x => x.alias == childAlias)) return;
const table = this.getFkTarget(column); const table = this.getFkTarget(column);
if (table && table.primaryKey) { if (table && table.primaryKey) {
@@ -191,15 +191,24 @@ export class TableGridDisplay extends GridDisplay {
const hintDescription = this.getDictionaryDescription(table); const hintDescription = this.getDictionaryDescription(table);
if (hintDescription) { if (hintDescription) {
const parentUniqueName = column.uniquePath.slice(0, -1).join('.'); const parentUniqueName = column.uniquePath.slice(0, -1).join('.');
this.addReferenceToSelect(select, parentUniqueName ? `${parentUniqueName}_ref` : 'basetbl', column); this.addReferenceToSelect(
const childAlias = `${column.uniqueName}_ref`; select,
parentUniqueName
? shortenIdentifier(`${parentUniqueName}_ref`, this.driver.dialect.maxIdentifierLength)
: 'basetbl',
column
);
const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength);
select.columns.push( select.columns.push(
...hintDescription.columns.map( ...hintDescription.columns.map(
columnName => columnName =>
({ ({
exprType: 'column', exprType: 'column',
columnName, columnName,
alias: `hint_${column.uniqueName}_${columnName}`, alias: shortenIdentifier(
`hint_${column.uniqueName}_${columnName}`,
this.driver.dialect.maxIdentifierLength
),
source: { alias: childAlias }, source: { alias: childAlias },
} as ColumnRefExpression) } as ColumnRefExpression)
) )
@@ -230,7 +239,7 @@ export class TableGridDisplay extends GridDisplay {
} }
getFkTarget(column: DisplayColumn) { getFkTarget(column: DisplayColumn) {
const { uniqueName, foreignKey, isForeignKeyUnique } = column; const { foreignKey, isForeignKeyUnique } = column;
if (!isForeignKeyUnique) return null; if (!isForeignKeyUnique) return null;
const pureName = foreignKey.refTableName; const pureName = foreignKey.refTableName;
const schemaName = foreignKey.refSchemaName; const schemaName = foreignKey.refSchemaName;

View File

@@ -32,6 +32,7 @@
"typescript": "^4.4.3" "typescript": "^4.4.3"
}, },
"dependencies": { "dependencies": {
"blueimp-md5": "^2.19.0",
"dbgate-query-splitter": "^4.11.7", "dbgate-query-splitter": "^4.11.7",
"dbgate-sqltree": "^6.0.0-alpha.1", "dbgate-sqltree": "^6.0.0-alpha.1",
"debug": "^4.3.4", "debug": "^4.3.4",

View File

@@ -9,6 +9,7 @@ import _isEmpty from 'lodash/isEmpty';
import _omitBy from 'lodash/omitBy'; import _omitBy from 'lodash/omitBy';
import { DataEditorTypesBehaviour } from 'dbgate-types'; import { DataEditorTypesBehaviour } from 'dbgate-types';
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject';
import md5 from 'blueimp-md5';
export const MAX_GRID_TEXT_LENGTH = 1000; // maximum length of text in grid cell, longer text is truncated export const MAX_GRID_TEXT_LENGTH = 1000; // maximum length of text in grid cell, longer text is truncated
@@ -737,3 +738,12 @@ export function setSqlFrontMatter(text: string, data: { [key: string]: any }, ya
const frontMatterContent = `-- >>>\n${yamlContentMapped}\n-- <<<\n`; const frontMatterContent = `-- >>>\n${yamlContentMapped}\n-- <<<\n`;
return frontMatterContent + (textClean || ''); return frontMatterContent + (textClean || '');
} }
export function shortenIdentifier(s: string, maxLength?: number) {
if (!maxLength || maxLength < 10) return s;
if (s.length <= maxLength) return s;
const hash = md5(s).substring(0, 8);
const partLength = Math.floor((maxLength - 9) / 2);
const restLength = maxLength - 10 - partLength;
return s.substring(0, partLength) + '_' + hash + '_' + s.substring(s.length - restLength);
}

View File

@@ -22,6 +22,7 @@ export interface SqlDialect {
requireStandaloneSelectForScopeIdentity?: boolean; requireStandaloneSelectForScopeIdentity?: boolean;
allowMultipleValuesInsert?: boolean; allowMultipleValuesInsert?: boolean;
useServerDatabaseFile?: boolean; useServerDatabaseFile?: boolean;
maxIdentifierLength?: number;
dropColumnDependencies?: string[]; dropColumnDependencies?: string[];
changeColumnDependencies?: string[]; changeColumnDependencies?: string[];

View File

@@ -18,6 +18,7 @@ const dialect = {
renameColumnDependencies: ['dependencies', 'foreignKeys', 'uniques'], renameColumnDependencies: ['dependencies', 'foreignKeys', 'uniques'],
defaultValueBeforeNullability: true, defaultValueBeforeNullability: true,
useServerDatabaseFile: true, useServerDatabaseFile: true,
maxIdentifierLength: 31,
quoteIdentifier(s) { quoteIdentifier(s) {
return `"${s}"`; return `"${s}"`;