Итак, я пишу скрипт, который запускает несколько различных postgres sql запросов, хранящихся в файлах, и записывает результаты (с некоторыми дополнительными вычислениями) обратно в выходную таблицу. Поскольку запросы могут быть добавлены или изменены для включения большего числа столбцов, сценарий попытается изменить выходную таблицу для включения соответствующих новых столбцов.
Я знаю, что могу извлечь postgres oid для столбцов в запросе, используя описание курсора, а затем выполнить запрос к postgres, чтобы преобразовать oid в строковую форму postgres тип данных:
colnames = [desc[0] for desc in cur.description]
coloids = [desc[1] for desc in cur.description]
coltypes = [get_pg_type_from_oid(x) for x in coloids]
...
oid_catalog = {
20: 'BIGINT',
23 : 'INTEGER',
1043: 'TEXT',
1700: 'REAL',
}
def get_pg_type_from_oid(oid):
if oid in oid_catalog:
log.debug("converting oid type {} into {}".format(oid, oid_catalog[oid]))
return oid_catalog[oid]
q = "select {}::oid::regtype".format(oid)
with conn, conn.cursor() as cur:
cur.execute(q)
newtype = cur.fetchone()[0]
log.debug("converting oid type {} into {}".format(oid, newtype))
oid_catalog[oid] = newtype
return newtype
Однако строки типа данных, возвращаемые моим get_pg_type_from_oid, по-видимому, имеют другой формат, чем те, которые я обычно использовал бы для создания новой таблицы или добавления столбцов (например, «изменяющийся символ» "вместо" VARCHAR (X) "и т. д.).
Есть ли более простой способ получить это отображение? Я только начал вручную жестко задавать c сопоставления с сохраненным oid_catalog, где мне нужно, но мне бы хотелось более общее и элегантное решение.
Кстати, есть ли способ получить результаты из cursor.fetchall () представляют себя в виде строки с необходимым форматированием для прямого включения в запрос?
В настоящее время я делаю это вручную (см. код ниже), но моя интуиция заключается в том, что должно быть лучший способ.
def stringify(l):
newl = []
for x in l:
if isinstance(x,float) or isinstance(x,Decimal):
newl.append("{0:.2f}".format(round(float(x),2)))
elif isinstance(x, datetime.datetime):
newl.append("(TIMESTAMP '{}')".format(x.isoformat()))
elif isinstance(x, datetime.date):
newl.append("'{}'".format(str(x)))
elif type(x) is str:
newl.append("'"+x+"'")
else: # type(x) == 'int':
#log.info("type else used for {}".format(x))
newl.append(str(x))
#log.debug("new string = {}".format(newl))
return list(newl)