Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在SqlAlchemy中,选择未测试的PostgreSQL数组无法按预期工作_Python_Postgresql_Sqlalchemy - Fatal编程技术网

Python 在SqlAlchemy中,选择未测试的PostgreSQL数组无法按预期工作

Python 在SqlAlchemy中,选择未测试的PostgreSQL数组无法按预期工作,python,postgresql,sqlalchemy,Python,Postgresql,Sqlalchemy,我做了一个SQL查询,它复制了一行,实际上是在表中删除并插入新的行,同时按给定的时间戳拆分其原始TSRANGE字段。 据我测试,它工作得很好。下面是一个演示,以说明我的意思并为方便起见: -演示初始化 创建随机表 uid VARCHAR36主键, 我是瓦查尔20, tsrange\u字段tsrange ; 创建扩展pgcrypto;-“gen_random_uuid”函数需要 插入public.random_表uid,id,tsrange_字段 gen_random_uuid,‘random_i

我做了一个SQL查询,它复制了一行,实际上是在表中删除并插入新的行,同时按给定的时间戳拆分其原始TSRANGE字段。 据我测试,它工作得很好。下面是一个演示,以说明我的意思并为方便起见:

-演示初始化 创建随机表 uid VARCHAR36主键, 我是瓦查尔20, tsrange\u字段tsrange ; 创建扩展pgcrypto;-“gen_random_uuid”函数需要 插入public.random_表uid,id,tsrange_字段 gen_random_uuid,‘random_id’,tsrange'2000-01-01','2020-01-01','['的值; -实际查询 以拆分器作为 选择uid,datetime 从随机表 加入unnestARRAY['2015-04-15'::时间戳,'2016-04-15'::时间戳,'2017-01-01'::时间戳,'2017-04-15'::时间戳]日期时间 在tsrange_字段@>datetime上 其中id='random_id' lowerrandom_table.tsrange_字段为空或lowerrandom_table.tsrange_字段!=日期时间 并且upperrandom_table.tsrange_字段为空或upperrandom_table.tsrange_字段!=日期时间 ,分为 从随机表中删除 使用拆分器 其中splitters.uid=random_table.uid 返回random_table.uid、id、tsrange_字段 插入随机_表uid、id、tsrange_字段 在id、tsrange\U字段中选择DISTINCT gen_random_uuid作为uid,id, 混乱[ 塔斯兰奇 案例 当LAGsplitters.datetime超过按拆分器划分的分区时。按拆分器划分的uid顺序。datetime不为NULL 然后Lagspitters.datetime超过按拆分器划分的分区。uid按拆分器排序。datetime ELSE lowertsrange_字段 终止 splitters.datetime, '[' , 塔斯兰奇 splitters.datetime, 案例 当LEADsplitters.datetime超过按拆分器划分的分区时。按拆分器划分的uid顺序。datetime不为NULL 然后按拆分器在分区上引导splitters.datetime.uid按拆分器排序.datetime ELSE UpperTSU字段 终止 '[' ]AS-tsu域 FROM to_be_splitted将拆分器连接到to_be_splitted.uid=splitters.uid 按TSU字段排序 返回*; 现在我想在sqlalchemy中翻译它,这就是我的问题所在。我生成了以下代码:

pip安装psycopg2,sqlalchemy 从日期时间导入日期时间 从sqlalchemy导入和_,case,cast,column,column,create_引擎,delete,func, insert、MetaData、or、select、Table、VARCHAR 来自sqlalchemy.dialogs.postgresql导入数组、TSRANGE、数组 元数据=元数据 随机表=表 “随机表”,元数据, 列'uid',VARCHAR36,主键=True, 列'id',VARCHAR20, 列'tsrange_field',tsrange 引擎=创建引擎'postgresql://test:test@本地主机:5432/test' def split_rowid,*日期时间: 此函数包含翻译尝试 splits=func.unnest[datetime中dt的dt]。别名“datetime” datetime\u col=列“datetime” 拆分器= 选择[RANDOM\u TABLE.c.uid,datetime\u col] 。从随机表格中选择。连接 分裂, onclause=RANDOM\u TABLE.c.tsrange\u field.op'@>'datetime\u col .何处_ 随机_TABLE.c.id==id, 或_func.lowerRANDOM_TABLE.c.tsrange_字段==无, 函数lowerRANDOM_TABLE.c.tsrange_field.op'!='datetime_col, 或_func.upperRANDOM_TABLE.c.tsrange_字段==无, 函数upperRANDOM\u TABLE.c.tsrange\u field.op'!='datetime\u col, .cte“拆分器” 待拆分= 删除随机表 .其中splitters.c.uid==RANDOM_TABLE.c.uid .returningRANDOM\u TABLE.c.uid,RANDOM\u TABLE.c.tsrange\u字段 .cte“待分割” window_params={'partition_by':列'uid', 'order_by':datetime_col} 上一个拆分器=函数lagdatetime列**窗口参数 下一个拆分器=函数前置日期时间列**窗口参数 下界大小写=大小写 [上一个拆分器!=无,上一个拆分器], else=函数lowercolumn'tRange\u field' 上界大小写=大小写 [下一个拆分器!=无,下一个拆分器], else_uu=func.uppercolumn'tsrange_field' 拆分范围=[ func.tsrange下限大小写,日期时间列,“[”, func.tsrangedatetime列,上限大小写,[' ] 拆分查询=选择[ 函数gen\u random\u uuid.标签'uid', 函数unnestsplit\u tsranges.别名“tsrange\u field”不起作用 ].独特的 列“tsrange\u字段” .从中选择 分裂 .joinsplitters,onclause=to_be_split.c.uid==splitters.c.uid .订购 列“tsrange\u字段” 整个查询= 插入随机表 .从中选择[列'uid',列'tsrange\u field',拆分查询 .returningcolumn'uid',column'tsrange\u field' 返回整个查询 带发动机。连接为接头: query=split_row'random_id',datetime.now 进口pdb;pdb.set_跟踪 printconn.executequery.fetchall 不幸的是,它失败了,并显示以下消息:

Traceback (most recent call last):
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
    cursor, statement, parameters, context
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
    cursor.execute(statement, parameters)
psycopg2.ProgrammingError: can't adapt type 'Function'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "stuck.py", line 85, in <module>
    print(conn.execute(query).fetchall())
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 988, in execute
    return meth(self, multiparams, params)
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
    distilled_params,
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1248, in _execute_context
    e, statement, parameters, cursor, context
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1466, in _handle_dbapi_exception
    util.raise_from_cause(sqlalchemy_exception, exc_info)
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 383, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 128, in reraise
    raise value.with_traceback(tb)
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
    cursor, statement, parameters, context
  File "/home/tryph/sql_split/.env/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) can't adapt type 'Function'
[SQL: WITH splitters AS 
(SELECT random_table.uid AS uid, datetime 
FROM random_table JOIN unnest(%(unnest_3)s) AS datetime ON random_table.tsrange_field @> datetime 
WHERE random_table.id = %(id_1)s AND (lower(random_table.tsrange_field) IS NULL OR (lower(random_table.tsrange_field) != datetime)) AND (upper(random_table.tsrange_field) IS NULL OR (upper(random_table.tsrange_field) != datetime))), 
to_be_split AS 
(DELETE FROM random_table USING splitters WHERE splitters.uid = random_table.uid RETURNING random_table.uid, random_table.tsrange_field)
 INSERT INTO random_table (uid, tsrange_field) SELECT DISTINCT ON (tsrange_field) gen_random_uuid() AS uid, tsrange_field.unnest_1 
FROM unnest(%(unnest_2)s) AS tsrange_field, to_be_split JOIN splitters ON to_be_split.uid = splitters.uid ORDER BY tsrange_field RETURNING uid, tsrange_field]
[parameters: {'unnest_2': [<sqlalchemy.sql.functions.Function at 0x7fba18954a20; tsrange>, <sqlalchemy.sql.functions.Function at 0x7fba18954b00; tsrange>], 'unnest_3': [datetime.datetime(2019, 5, 3, 23, 37, 1, 773118)], 'id_1': 'random_id'}]
(Background on this error at: http://sqlalche.me/e/f405)
查看生成的SQL,我注意到原始SQL查询的SELECT中的unnestARRAY[…]AS tsrange_字段在FROM子句中呈现,我不知道为什么。此外,消息psycopg2.ProgrammingError:can't adapt type'Function'没有提供很大的帮助,并且似乎与最不合理的错误呈现无关


任何关于发生了什么以及如何修复的提示都将不胜感激。

正如您所指出的,有问题的部分是

split_query = select([
        func.gen_random_uuid().label('uid'),
        func.unnest(split_tsranges).alias('tsrange_field')  # does not work
    ])
问题是,它用于生成适合FROM子句的命名别名,因此SQLAlchemy将其移到了那里。使用标签“tsrange\u field”生成为tsrange\u field。另一个问题是SQLAlchemy将列表按原样传递给DB-API驱动程序,而DB-API驱动程序不知道如何处理SQLAlchemy构造。在调用中包装列表,以便SQLAlchemy使用嵌套表达式呈现数组文字:

split_tsranges = array([
        func.tsrange(lower_bound_case, datetime_col, '[)'),
        func.tsrange(datetime_col, upper_bound_case, '[)')
    ])
我应该亲眼看到别名问题。。。非常感谢这个非常有用的答案。现在它工作得很好