Skip to content

Commit 0c81e17

Browse files
committed
Merge commit 'refs/pull/18/head' of https://github.com/hackolade/PostgreSQL
2 parents 627f3bb + e856a46 commit 0c81e17

File tree

7 files changed

+108
-48
lines changed

7 files changed

+108
-48
lines changed

forward_engineering/configs/templates.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ module.exports = {
99
'CREATE${temporary} TABLE${ifNotExist} ${name} (\n' +
1010
'${columnDefinitions}${keyConstraints}${checkConstraints}${foreignKeyConstraints}\n' +
1111
')${options};\n\n${comment}${columnDescriptions}',
12+
13+
createTablePartitionOf:
14+
'CREATE${temporary} TABLE${ifNotExist} ${name}\n' +
15+
'${partitionOf} ${openParenthesis}${keyConstraints}${checkConstraints}${foreignKeyConstraints}\n' +
16+
'${closeParenthesis}${options};\n\n${comment}${columnDescriptions}',
1217

1318
columnDefinition: '${name} ${type}${collation}${primaryKey}${uniqueKey}${defaultValue}${notNull}',
1419

forward_engineering/ddlProvider.js

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ module.exports = (baseProvider, options, app) => {
146146
temporary,
147147
unlogged,
148148
selectStatement,
149+
partitionOf,
150+
partitionBounds,
149151
},
150152
isActivated
151153
) {
@@ -162,32 +164,47 @@ module.exports = (baseProvider, options, app) => {
162164
key => key.statement
163165
);
164166
const keyConstraintsString = generateConstraintsString(dividedKeysConstraints, isActivated);
167+
const keyConstraintsValue = partitionOf ? keyConstraintsString?.slice(1) : keyConstraintsString
165168

166169
const dividedForeignKeys = divideIntoActivatedAndDeactivated(foreignKeyConstraints, key => key.statement);
167170
const foreignKeyConstraintsString = generateConstraintsString(dividedForeignKeys, isActivated);
168171

169172
const columnDescriptions = '\n' + getColumnComments(tableName, columnDefinitions);
170-
171-
const tableStatement = assignTemplates(templates.createTable, {
172-
temporary: getTableTemporaryValue(temporary, unlogged),
173-
ifNotExist: ifNotExistStr,
174-
name: tableName,
175-
columnDefinitions: '\t' + _.join(columns, ',\n\t'),
176-
keyConstraints: keyConstraintsString,
177-
checkConstraints: !_.isEmpty(checkConstraints) ? ',\n\t' + _.join(checkConstraints, ',\n\t') : '',
178-
foreignKeyConstraints: foreignKeyConstraintsString,
179-
options: getTableOptions({
180-
inherits,
181-
partitioning,
182-
usingMethod,
183-
on_commit,
184-
storage_parameter,
185-
table_tablespace_name,
186-
selectStatement,
187-
}),
188-
comment: description ? comment : '',
189-
columnDescriptions,
190-
});
173+
const template = partitionOf ? templates.createTablePartitionOf : templates.createTable;
174+
175+
const checkConstraintPrefix = partitionOf && !keyConstraintsString ? '\n\t' : ',\n\t';
176+
const checkConstraintsValue = !_.isEmpty(checkConstraints)
177+
? wrap(_.join(checkConstraints, ',\n\t'), checkConstraintPrefix, '')
178+
: '';
179+
180+
const isEmptyPartitionBody = partitionOf && !keyConstraintsValue && !checkConstraintsValue && !foreignKeyConstraintsString
181+
const openParenthesis = isEmptyPartitionBody ? '': '('
182+
const closeParenthesis = isEmptyPartitionBody ? '' : ')'
183+
184+
const tableStatement = assignTemplates(template, {
185+
temporary: getTableTemporaryValue(temporary, unlogged),
186+
ifNotExist: ifNotExistStr,
187+
name: tableName,
188+
columnDefinitions: !partitionOf ? '\t' + _.join(columns, ',\n\t') : '',
189+
keyConstraints: keyConstraintsValue,
190+
checkConstraints: checkConstraintsValue,
191+
foreignKeyConstraints: foreignKeyConstraintsString,
192+
options: getTableOptions({
193+
inherits,
194+
partitioning,
195+
usingMethod,
196+
on_commit,
197+
storage_parameter,
198+
table_tablespace_name,
199+
selectStatement,
200+
partitionBounds,
201+
}),
202+
comment: description ? comment : '',
203+
partitionOf: partitionOf ? ` PARTITION OF ${partitionOf} ` : '',
204+
columnDescriptions,
205+
openParenthesis,
206+
closeParenthesis,
207+
});
191208

192209
return tableStatement;
193210
},
@@ -518,25 +535,31 @@ module.exports = (baseProvider, options, app) => {
518535
.value();
519536
const partitioning = _.first(detailsTab.partitioning) || {};
520537
const compositePartitionKey = keyHelper.getKeys(partitioning.compositePartitionKey, jsonSchema);
538+
const partitionParent = _.get(tableData, `relatedSchemas[${detailsTab.partitionOf}]`);
539+
const partitionOf = partitionParent
540+
? getNamePrefixedWithSchemaName(partitionParent.collectionName, partitionParent.bucketName)
541+
: '';
521542

522543
return {
523-
...tableData,
524-
keyConstraints: keyHelper.getTableKeyConstraints(jsonSchema),
525-
inherits: parentTables,
526-
selectStatement: _.trim(detailsTab.selectStatement),
527-
partitioning: _.assign({}, partitioning, { compositePartitionKey }),
528-
..._.pick(
529-
detailsTab,
530-
'temporary',
531-
'unlogged',
532-
'description',
533-
'ifNotExist',
534-
'usingMethod',
535-
'on_commit',
536-
'storage_parameter',
537-
'table_tablespace_name'
538-
),
539-
};
544+
...tableData,
545+
partitionOf,
546+
keyConstraints: keyHelper.getTableKeyConstraints(jsonSchema),
547+
inherits: parentTables,
548+
selectStatement: _.trim(detailsTab.selectStatement),
549+
partitioning: _.assign({}, partitioning, { compositePartitionKey }),
550+
..._.pick(
551+
detailsTab,
552+
'temporary',
553+
'unlogged',
554+
'description',
555+
'ifNotExist',
556+
'usingMethod',
557+
'on_commit',
558+
'storage_parameter',
559+
'table_tablespace_name',
560+
'partitionBounds'
561+
),
562+
};
540563
},
541564

542565
hydrateViewColumn(data) {

forward_engineering/helpers/tableHelper.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = ({ _, getColumnsList, checkAllKeysDeactivated }) => {
1616

1717
const statements = [
1818
{ key: 'inherits', getValue: getBasicValue('INHERITS') },
19+
{ key: 'partitionBounds', getValue: getBasicValue('') },
1920
{ key: 'partitioning', getValue: getPartitioning },
2021
{ key: 'usingMethod', getValue: getBasicValue('USING') },
2122
{ key: 'storage_parameter', getValue: getStorageParameters },

properties_pane/entity_level/entityLevelConfig.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,22 @@ making sure that you maintain a proper JSON format.
159159
}
160160
]
161161
},
162+
{
163+
"propertyName": "Partition of",
164+
"propertyKeyword": "partitionOf",
165+
"propertyType": "selecthashed",
166+
"template": "entities",
167+
"withEmptyOption": true,
168+
"excludeCurrent": true
169+
},
170+
{
171+
"propertyName": "Partition bounds",
172+
"propertyKeyword": "partitionBounds",
173+
"propertyTooltip": "Partition bounds",
174+
"propertyType": "details",
175+
"template": "textarea",
176+
"markdown": false
177+
},
162178
{
163179
"propertyName": "Partitioning",
164180
"propertyKeyword": "partitioning",

reverse_engineering/helpers/postgresHelpers/tableHelper.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,14 @@ const prepareTableLevelData = (tableLevelData, tableToastOptions) => {
290290
const unlogged = tableLevelData?.relpersistence === 'u';
291291
const storage_parameter = prepareStorageParameters(tableLevelData?.reloptions, tableToastOptions);
292292
const table_tablespace_name = tableLevelData?.spcname;
293+
const partitionBounds = tableLevelData.partition_expr;
293294

294295
return {
295296
temporary,
296297
unlogged,
297298
storage_parameter,
298299
table_tablespace_name,
300+
partitionBounds,
299301
};
300302
};
301303

reverse_engineering/helpers/postgresService.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,15 @@ module.exports = {
149149
const [viewsNames, tablesNames] = _.partition(entitiesNames, isViewByName);
150150

151151
const allTablesList = tablesNames.flatMap(tableName => [
152-
tableName,
153-
..._.filter(partitions, { parent_name: tableName }).map(({ child_name }) => child_name),
152+
{ tableName },
153+
..._.filter(partitions, { parent_name: tableName }).map(({ child_name, is_parent_partitioned }) => ({
154+
isParentPartitioned: is_parent_partitioned,
155+
tableName: child_name,
156+
})),
154157
]);
155158

156159
const tables = await mapPromises(
157-
allTablesList,
160+
_.uniq(allTablesList),
158161
_.bind(
159162
this._retrieveSingleTableData,
160163
this,
@@ -234,7 +237,13 @@ module.exports = {
234237
return getUserDefinedTypes(udtsWithColumns, domainTypesWithConstraints);
235238
},
236239

237-
async _retrieveSingleTableData(recordSamplingSettings, schemaOid, schemaName, userDefinedTypes, tableName) {
240+
async _retrieveSingleTableData(
241+
recordSamplingSettings,
242+
schemaOid,
243+
schemaName,
244+
userDefinedTypes,
245+
{ tableName, isParentPartitioned },
246+
) {
238247
logger.progress('Get table data', schemaName, tableName);
239248

240249
const tableLevelData = await db.queryTolerant(
@@ -268,10 +277,10 @@ module.exports = {
268277
const tableData = {
269278
partitioning,
270279
description,
271-
inherits,
272280
Indxs: tableIndexes,
273281
...tableLevelProperties,
274282
...tableConstraint,
283+
...(isParentPartitioned ? { partitionOf: _.first(inherits)?.parentTable } : { inherits }),
275284
};
276285

277286
const entityLevel = clearEmptyPropertiesInObject(tableData);

reverse_engineering/helpers/queryConstants.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,14 @@ const queryConstants = {
109109
AND pg_class.relkind = ANY('{"r","v","t","m","p"}'))
110110
AS catalog_table_data
111111
ON (catalog_table_data.table_name = tables.table_name AND catalog_table_data.table_schema = tables.table_schema)
112-
WHERE tables.table_schema = $1;`,
112+
LEFT JOIN (SELECT relname AS child_name FROM pg_catalog.pg_inherits AS inherit
113+
LEFT JOIN pg_catalog.pg_class AS child ON (child.oid = inherit.inhrelid)) AS inherited_tables
114+
ON (inherited_tables.child_name = tables.table_name)
115+
WHERE inherited_tables.child_name IS NULL
116+
AND tables.table_schema = $1;`,
113117
GET_NAMESPACE_OID: 'SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = $1',
114118
GET_TABLE_LEVEL_DATA: `
115-
SELECT pc.oid, pc.relpersistence, pc.reloptions, pt.spcname
119+
SELECT pc.oid, pc.relpersistence, pc.reloptions, pt.spcname, pg_get_expr(pc.relpartbound, pc.oid) AS partition_expr
116120
FROM pg_catalog.pg_class AS pc
117121
LEFT JOIN pg_catalog.pg_tablespace AS pt
118122
ON pc.reltablespace = pt.oid
@@ -279,12 +283,12 @@ const queryConstants = {
279283
GET_PARTITIONS: `
280284
SELECT
281285
inher_child.relname AS child_name,
282-
inher_parent.relname AS parent_name
286+
inher_parent.relname AS parent_name,
287+
CASE WHEN inher_parent.relkind = 'p' THEN TRUE ELSE FALSE END AS is_parent_partitioned
283288
FROM pg_inherits
284289
LEFT JOIN pg_class AS inher_child ON (inher_child.oid = pg_inherits.inhrelid)
285290
LEFT JOIN pg_class AS inher_parent ON (inher_parent.oid = pg_inherits.inhparent)
286-
WHERE inher_parent.relkind = 'p'
287-
AND inher_parent.relnamespace = $1;`,
291+
WHERE inher_parent.relnamespace = $1;`,
288292
};
289293

290294
const getQueryName = query => {

0 commit comments

Comments
 (0)