Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | 2x 2x 2x 2x 2x 3x 2x 3x 3x 3x 3x 3x 5x 5x 5x 5x 6x 6x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 14x 14x 14x 14x 14x 1x 14x 14x 14x 3x 3x 14x 2x 2x 16x 3x 3x 3x | /* * Deepkit Framework * Copyright (C) 2021 Deepkit UG, Marc J. Schmidt * * This program is free software: you can redistribute it and/or modify * it under the terms of the MIT License. * * You should have received a copy of the MIT License along with this program. */ import { DatabaseModel, ForeignKey, Table, parseType, SchemaParser } from '@deepkit/sql'; export class PostgresSchemaParser extends SchemaParser { protected defaultPrecisions = { 'char': 1, 'character': 1, 'integer': 32, 'bigint': 64, 'smallint': 16, 'double precision': 53 }; async parse(database: DatabaseModel, limitTableNames?: string[]) { await this.parseTables(database, limitTableNames); for (const table of database.tables) { await this.addColumns(table); } for (const table of database.tables) { await this.addIndexes(table); await this.addForeignKeys(database, table); } } protected async addIndexes(table: Table) { const oid = `'"${table.schemaName || 'public'}"."${table.getName()}"'::regclass`; const indexes = await this.connection.execAndReturnAll(` SELECT DISTINCT ON (cls.relname) cls.relname as idxname, indkey, idx.indisunique as unique, idx.indisprimary as primary FROM pg_index idx JOIN pg_class cls ON cls.oid = indexrelid WHERE indrelid = ${oid} AND NOT indisprimary ORDER BY cls.relname `); for (const row of indexes) { Iif (row.primary) { table.getColumn(row.column_name).isPrimaryKey = true; continue; } const index = table.addIndex(row.idxname, row.unique); const attnums = row.indkey.split(' '); for (const attnum of attnums) { const column = await this.connection.execAndReturnSingle(` SELECT a.attname FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid WHERE c.oid = ${oid} AND a.attnum = ${attnum} AND NOT a.attisdropped ORDER BY a.attnum `); index.addColumn(column.attname); } } } protected async addForeignKeys(database: DatabaseModel, table: Table) { const rows = await this.connection.execAndReturnAll(` select kcu.table_name as table_name, kcu.constraint_name as constraint_name, rel_kcu.table_name as referenced_table_name, rel_kcu.constraint_schema as referenced_schema_name, kcu.column_name as column_name, rel_kcu.column_name as referenced_column_name, kcu.constraint_name, rco.update_rule, rco.delete_rule from information_schema.table_constraints tco join information_schema.key_column_usage kcu on tco.constraint_schema = kcu.constraint_schema and tco.constraint_name = kcu.constraint_name join information_schema.referential_constraints rco on tco.constraint_schema = rco.constraint_schema and tco.constraint_name = rco.constraint_name join information_schema.key_column_usage rel_kcu on rco.unique_constraint_schema = rel_kcu.constraint_schema and rco.unique_constraint_name = rel_kcu.constraint_name and kcu.ordinal_position = rel_kcu.ordinal_position where tco.table_name = '${table.getName()}' and tco.table_schema = '${table.schemaName || 'public'}' and tco.constraint_schema = tco.table_schema and tco.constraint_type = 'FOREIGN KEY' order by kcu.table_schema, kcu.table_name, kcu.ordinal_position `); let lastId: string | undefined; let foreignKey: ForeignKey | undefined; for (const row of rows) { Eif (row.constraint_name !== lastId) { lastId = row.constraint_name; const foreignTable = database.getTable(row.referenced_table_name); foreignKey = table.addForeignKey(row.constraint_name, foreignTable); } Eif (foreignKey) { foreignKey.addReference(row.column_name, row.referenced_column_name); foreignKey.onUpdate = row.update_rule; foreignKey.onDelete = row.delete_rule; } } } protected async addColumns(table: Table) { const rows = await this.connection.execAndReturnAll(` SELECT column_name, data_type, column_default, is_nullable, numeric_precision, numeric_scale, character_maximum_length FROM information_schema.columns WHERE table_schema = '${table.schemaName || 'public'}' AND table_name = '${table.getName()}' `); for (const row of rows) { const column = table.addColumn(row.column_name); parseType(column, row.data_type); const size = row.character_maximum_length || row.numeric_precision; const scale = row.numeric_scale; if (size && column.type && size !== this.defaultPrecisions[column.type]) { column.size = size; } Iif (scale) column.scale = scale; column.isNotNull = row.is_nullable === 'NO'; if ('string' === typeof row.column_default) { Eif (row.column_default.includes('nextval(') && row.column_default.includes('::regclass')) { column.isAutoIncrement = true; } else { column.defaultValue = JSON.parse(row.column_default); } } Iif (row.data_type.includes('SERIAL')) { column.isAutoIncrement = true; } } } protected async parseTables(database: DatabaseModel, limitTableNames?: string[]) { const rows = await this.connection.execAndReturnAll(` select table_name, table_schema as schema_name from information_schema.tables where table_schema not like 'pg_%' and table_schema = current_schema() and table_name != 'geometry_columns' and table_name != 'spatial_ref_sys' and table_type != 'VIEW' and table_schema = '${database.schemaName || 'public'}' order by table_name `); for (const row of rows) { if (limitTableNames && !limitTableNames.includes(row.table_name)) continue; const table = database.addTable(row.table_name); Iif (row.schema_name !== 'public') { table.schemaName = row.schema_name || database.schemaName; } else { table.schemaName = database.schemaName; } } } } |