处理 psycopg2 中的重复字段
handle duplicates fields in psycopg2
我正在使用 Flask(Python3.4) 和 psycopg2 编写 Web 应用程序以连接到 postgres 9.4 数据库。
我在我的网络应用程序中有一个选项,用户可以在其中编写自己的查询并使用网络应用程序执行它,并在 html table 中获得输出作为响应。
我将光标用作 conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
我无法更改,因为它也被网络应用程序的其他部分使用。
我的一位用户写了 SQL 如下所示,
SELECT
name || ' - ' || address,
id,
salary || '; ' || id from company;
psycopg2 的输出(错误):
?column? id ?column?
text integer (4) text
500.55; 1 1 500.55; 1
500.55; 2 2 500.55; 2
500.55; 3 3 500.55; 3
500.55; 4 4 500.55; 4
999.99; 5 5 999.99; 5
这里我得到的结果是错误的,因为 key/field 名称重复 ?column? 第二次出现覆盖第一个。
预期输出为:
?column? id ?column?
text integer (4) text
AAA - XY 1 500.55; 1
BBB - ZZ 2 500.55; 2
ABC - YY 3 500.55; 3
ABC - CC 4 500.55; 4
ABC - DD 5 999.99; 5
发送响应的服务器端代码:
# Fetch the column info
if cur.description is not None:
colinfo = [desc for desc in cur.description]
# Any rows?
if cur.rowcount > 0:
result = []
try:
for row in cur:
result.append(dict(row))
except psycopg2.ProgrammingError:
result = None
# response for html table
return Response(
response=json.dumps(colinfo, result),
status=status,
mimetype="text/json"
)
请提出建议,如何通过最少的代码更改来解决此问题?
同时我也提出了 psycopg2 的问题,
https://github.com/psycopg/psycopg2/issues/454
基本问题是字典条目必须具有唯一键。如果将有多个列具有相同的名称,则列名不能用作键。但是,您可以检查一下,如果有重复的列名,请以某种方式使其唯一:
# Fetch the column info
if cur.description is not None:
colinfo = [desc for desc in cur.description]
# Any rows?
if cur.rowcount > 0:
result = []
rowdict = {}
colnames = [desc[0] for desc in cur.description]
try:
for row in cur:
rowdict = {}
for x in range(0, len(row)):
# make sure column name is unique, if not append index number
if colnames[x] in rowdict:
rowdict[colnames[x] + "_" + str(x)] = row[x]
else:
rowdict[colnames[x]] = row[x]
result.append(rowdict)
except psycopg2.ProgrammingError:
result = None
# response for html table
return Response(
response=json.dumps(colinfo, result),
status=status,
mimetype="text/json"
)
根据您在客户端所做的工作,您可能还必须更新 colinfo 以反映所做的任何列名更改。另一种选择是 return 如果存在重复的列名,则显示一条明确的错误消息,以便用户可以控制他们返回的列名。
这最终是 psycopg2 中的一个错误,但它只是 returning 了 postgres 在这种情况下为列名提供的内容。目前还不清楚它应该做什么。
我假设您已经考虑并处理了与从客户端执行 SQL 相关的严重信息安全风险。我不是想说教,但它是一个 public 论坛,如果其他人想要做这样的事情,我会因为没有提及而失职。
我正在使用 Flask(Python3.4) 和 psycopg2 编写 Web 应用程序以连接到 postgres 9.4 数据库。
我在我的网络应用程序中有一个选项,用户可以在其中编写自己的查询并使用网络应用程序执行它,并在 html table 中获得输出作为响应。
我将光标用作 conn.cursor(cursor_factory=psycopg2.extras.DictCursor) 我无法更改,因为它也被网络应用程序的其他部分使用。
我的一位用户写了 SQL 如下所示,
SELECT
name || ' - ' || address,
id,
salary || '; ' || id from company;
psycopg2 的输出(错误):
?column? id ?column?
text integer (4) text
500.55; 1 1 500.55; 1
500.55; 2 2 500.55; 2
500.55; 3 3 500.55; 3
500.55; 4 4 500.55; 4
999.99; 5 5 999.99; 5
这里我得到的结果是错误的,因为 key/field 名称重复 ?column? 第二次出现覆盖第一个。
预期输出为:
?column? id ?column?
text integer (4) text
AAA - XY 1 500.55; 1
BBB - ZZ 2 500.55; 2
ABC - YY 3 500.55; 3
ABC - CC 4 500.55; 4
ABC - DD 5 999.99; 5
发送响应的服务器端代码:
# Fetch the column info
if cur.description is not None:
colinfo = [desc for desc in cur.description]
# Any rows?
if cur.rowcount > 0:
result = []
try:
for row in cur:
result.append(dict(row))
except psycopg2.ProgrammingError:
result = None
# response for html table
return Response(
response=json.dumps(colinfo, result),
status=status,
mimetype="text/json"
)
请提出建议,如何通过最少的代码更改来解决此问题?
同时我也提出了 psycopg2 的问题, https://github.com/psycopg/psycopg2/issues/454
基本问题是字典条目必须具有唯一键。如果将有多个列具有相同的名称,则列名不能用作键。但是,您可以检查一下,如果有重复的列名,请以某种方式使其唯一:
# Fetch the column info
if cur.description is not None:
colinfo = [desc for desc in cur.description]
# Any rows?
if cur.rowcount > 0:
result = []
rowdict = {}
colnames = [desc[0] for desc in cur.description]
try:
for row in cur:
rowdict = {}
for x in range(0, len(row)):
# make sure column name is unique, if not append index number
if colnames[x] in rowdict:
rowdict[colnames[x] + "_" + str(x)] = row[x]
else:
rowdict[colnames[x]] = row[x]
result.append(rowdict)
except psycopg2.ProgrammingError:
result = None
# response for html table
return Response(
response=json.dumps(colinfo, result),
status=status,
mimetype="text/json"
)
根据您在客户端所做的工作,您可能还必须更新 colinfo 以反映所做的任何列名更改。另一种选择是 return 如果存在重复的列名,则显示一条明确的错误消息,以便用户可以控制他们返回的列名。
这最终是 psycopg2 中的一个错误,但它只是 returning 了 postgres 在这种情况下为列名提供的内容。目前还不清楚它应该做什么。
我假设您已经考虑并处理了与从客户端执行 SQL 相关的严重信息安全风险。我不是想说教,但它是一个 public 论坛,如果其他人想要做这样的事情,我会因为没有提及而失职。