Skip to content

Commit 000f28a

Browse files
committed
Catch db connection errors when collecting column metadata
1 parent 88a0b31 commit 000f28a

File tree

1 file changed

+109
-104
lines changed

1 file changed

+109
-104
lines changed

src/config_generator/qgs_reader.py

Lines changed: 109 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -612,110 +612,115 @@ def __column_metadata(self, field_metadata, datasource, column, data_type_only =
612612
column=column
613613
))
614614
db = self.db_engine.db_engine(datasource["database"])
615-
with db.connect() as conn:
616-
# execute query
617-
results = conn.execute(sql)
618-
619-
if results.rowcount == 0:
620-
# fallback to query SQL for materialized views
621-
622-
# SQL partially based on definition of information_schema.columns:
623-
# https://github.com/postgres/postgres/tree/master/src/backendsrc/backend/catalog/information_schema.sql#L674
624-
sql_mv = sql_text("""
625-
SELECT
626-
ns.nspname AS table_schema,
627-
c.relname AS table_name,
628-
a.attname AS column_name,
629-
format_type(a.atttypid, null) AS data_type,
630-
CASE
631-
WHEN a.atttypmod = -1 /* default typmod */
632-
THEN NULL
633-
WHEN a.atttypid IN (1042, 1043) /* char, varchar */
634-
THEN a.atttypmod - 4
635-
WHEN a.atttypid IN (1560, 1562) /* bit, varbit */
636-
THEN a.atttypmod
637-
ELSE
638-
NULL
639-
END AS character_maximum_length,
640-
CASE a.atttypid
641-
WHEN 21 /*int2*/ THEN 16
642-
WHEN 23 /*int4*/ THEN 32
643-
WHEN 20 /*int8*/ THEN 64
644-
WHEN 1700 /*numeric*/ THEN
645-
CASE
646-
WHEN a.atttypmod = -1
647-
THEN NULL
648-
ELSE ((a.atttypmod - 4) >> 16) & 65535
649-
END
650-
WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
651-
WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
652-
ELSE NULL
653-
END AS numeric_precision,
654-
CASE
655-
WHEN a.atttypid IN (21, 23, 20) /* int */ THEN 0
656-
WHEN a.atttypid IN (1700) /* numeric */ THEN
657-
CASE
658-
WHEN a.atttypmod = -1
659-
THEN NULL
660-
ELSE (a.atttypmod - 4) & 65535
661-
END
662-
ELSE NULL
663-
END AS numeric_scale
664-
FROM pg_catalog.pg_class c
665-
JOIN pg_catalog.pg_namespace ns ON ns.oid = c.relnamespace
666-
JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
667-
WHERE
668-
/* tables, views, materialized views */
669-
c.relkind in ('r', 'v', 'm')
670-
AND ns.nspname = '{schema}'
671-
AND c.relname = '{table}'
672-
AND a.attname = '{column}'
673-
ORDER BY nspname, relname, attnum
674-
""".format(
675-
schema=datasource["schema"],
676-
table=datasource["table_name"],
677-
column=column
678-
))
679-
results = conn.execute(sql_mv)
680-
681-
682-
row = results.mappings().fetchone()
683-
if not row:
684-
self.logger.warn(f"Failed to query column metadata of column {column} from table {datasource["schema"]}.{datasource["table_name"]}")
685-
return
686-
687-
# Field data type
688-
data_type = row['data_type']
689-
field_metadata['data_type'] = data_type
690-
691-
if not data_type_only:
692-
# Constraints from data type
693-
# NOTE: any existing QGIS field constraints take precedence
694-
ranges = {
695-
'smallint': {'min': -32768, 'max': 32767},
696-
'integer': {'min': -2147483648, 'max': 2147483647},
697-
'bigint': {'min': -9223372036854775808, 'max': 9223372036854775807}
698-
}
699-
constraints = field_metadata['constraints']
700-
if (data_type in ['character', 'character varying'] and
701-
row['character_maximum_length']):
702-
constraints['maxlength'] = row['character_maximum_length']
703-
elif data_type == 'numeric' and row['numeric_precision']:
704-
step = pow(10, -row['numeric_scale'])
705-
max_value = pow(
706-
10, row['numeric_precision'] - row['numeric_scale']
707-
) - step
708-
constraints['numeric_precision'] = row['numeric_precision']
709-
constraints['numeric_scale'] = row['numeric_scale']
710-
if not 'step' in constraints:
711-
constraints['step'] = step
712-
ranges['numeric'] = {'min': -max_value, 'max': max_value}
713-
714-
if data_type in ranges:
715-
if not 'min' in constraints:
716-
constraints['min'] = ranges[data_type]['min']
717-
if not 'max' in constraints:
718-
constraints['max'] = ranges[data_type]['max']
615+
try:
616+
with db.connect() as conn:
617+
# execute query
618+
results = conn.execute(sql)
619+
620+
if results.rowcount == 0:
621+
# fallback to query SQL for materialized views
622+
623+
# SQL partially based on definition of information_schema.columns:
624+
# https://github.com/postgres/postgres/tree/master/src/backendsrc/backend/catalog/information_schema.sql#L674
625+
sql_mv = sql_text("""
626+
SELECT
627+
ns.nspname AS table_schema,
628+
c.relname AS table_name,
629+
a.attname AS column_name,
630+
format_type(a.atttypid, null) AS data_type,
631+
CASE
632+
WHEN a.atttypmod = -1 /* default typmod */
633+
THEN NULL
634+
WHEN a.atttypid IN (1042, 1043) /* char, varchar */
635+
THEN a.atttypmod - 4
636+
WHEN a.atttypid IN (1560, 1562) /* bit, varbit */
637+
THEN a.atttypmod
638+
ELSE
639+
NULL
640+
END AS character_maximum_length,
641+
CASE a.atttypid
642+
WHEN 21 /*int2*/ THEN 16
643+
WHEN 23 /*int4*/ THEN 32
644+
WHEN 20 /*int8*/ THEN 64
645+
WHEN 1700 /*numeric*/ THEN
646+
CASE
647+
WHEN a.atttypmod = -1
648+
THEN NULL
649+
ELSE ((a.atttypmod - 4) >> 16) & 65535
650+
END
651+
WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
652+
WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
653+
ELSE NULL
654+
END AS numeric_precision,
655+
CASE
656+
WHEN a.atttypid IN (21, 23, 20) /* int */ THEN 0
657+
WHEN a.atttypid IN (1700) /* numeric */ THEN
658+
CASE
659+
WHEN a.atttypmod = -1
660+
THEN NULL
661+
ELSE (a.atttypmod - 4) & 65535
662+
END
663+
ELSE NULL
664+
END AS numeric_scale
665+
FROM pg_catalog.pg_class c
666+
JOIN pg_catalog.pg_namespace ns ON ns.oid = c.relnamespace
667+
JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
668+
WHERE
669+
/* tables, views, materialized views */
670+
c.relkind in ('r', 'v', 'm')
671+
AND ns.nspname = '{schema}'
672+
AND c.relname = '{table}'
673+
AND a.attname = '{column}'
674+
ORDER BY nspname, relname, attnum
675+
""".format(
676+
schema=datasource["schema"],
677+
table=datasource["table_name"],
678+
column=column
679+
))
680+
results = conn.execute(sql_mv)
681+
682+
683+
row = results.mappings().fetchone()
684+
if not row:
685+
self.logger.warn(f"Failed to query column metadata of column {column} from table {datasource["schema"]}.{datasource["table_name"]} of {datasource["database"]}")
686+
return
687+
688+
# Field data type
689+
data_type = row['data_type']
690+
field_metadata['data_type'] = data_type
691+
692+
if not data_type_only:
693+
# Constraints from data type
694+
# NOTE: any existing QGIS field constraints take precedence
695+
ranges = {
696+
'smallint': {'min': -32768, 'max': 32767},
697+
'integer': {'min': -2147483648, 'max': 2147483647},
698+
'bigint': {'min': -9223372036854775808, 'max': 9223372036854775807}
699+
}
700+
constraints = field_metadata['constraints']
701+
if (data_type in ['character', 'character varying'] and
702+
row['character_maximum_length']):
703+
constraints['maxlength'] = row['character_maximum_length']
704+
elif data_type == 'numeric' and row['numeric_precision']:
705+
step = pow(10, -row['numeric_scale'])
706+
max_value = pow(
707+
10, row['numeric_precision'] - row['numeric_scale']
708+
) - step
709+
constraints['numeric_precision'] = row['numeric_precision']
710+
constraints['numeric_scale'] = row['numeric_scale']
711+
if not 'step' in constraints:
712+
constraints['step'] = step
713+
ranges['numeric'] = {'min': -max_value, 'max': max_value}
714+
715+
if data_type in ranges:
716+
if not 'min' in constraints:
717+
constraints['min'] = ranges[data_type]['min']
718+
if not 'max' in constraints:
719+
constraints['max'] = ranges[data_type]['max']
720+
721+
except:
722+
self.logger.warn(f"Failed to query column metadata of column {column} from table {datasource["schema"]}.{datasource["table_name"]} of {datasource["database"]}")
723+
return
719724

720725

721726
def __generate_edit_form(self, project, qgs_dir, map_prefix, shortnames, maplayer, layer_metadata, layername, theme_item):

0 commit comments

Comments
 (0)