在视图中使用hstore比较转储和还原PostgreSQL数据库失败
我有一个比较两个在视图中使用hstore比较转储和还原PostgreSQL数据库失败,postgresql,hstore,postgresql-9.3,pg-restore,Postgresql,Hstore,Postgresql 9.3,Pg Restore,我有一个比较两个hstore列的视图 当我转储并还原此数据库时,还原失败,并显示以下错误消息: Importing /tmp/hstore_test_2014-05-12.backup... pg_restore: [archiver (db)] Error while PROCESSING TOC: pg_restore: [archiver (db)] Error from TOC entry 172; 1259 1358132 VIEW hstore_test_view xxxx pg_r
hstore
列的视图
当我转储并还原此数据库时,还原失败,并显示以下错误消息:
Importing /tmp/hstore_test_2014-05-12.backup...
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 172; 1259 1358132 VIEW hstore_test_view xxxx
pg_restore: [archiver (db)] could not execute query: ERROR: operator does not exist: public.hstore = public.hstore
LINE 2: SELECT NULLIF(hstore_test_table.column1, hstore_test_table....
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Command was: CREATE VIEW hstore_test_view AS
SELECT NULLIF(hstore_test_table.column1, hstore_test_table.column2) AS "nullif"
FROM hst...
pg_restore: [archiver (db)] could not execute query: ERROR: relation "hstore_test_schema.hstore_test_view" does not exist
Command was: ALTER TABLE hstore_test_schema.hstore_test_view OWNER TO xxxx;
我可以通过以下步骤在PostgreSQL 9.3.0中创建此错误:
CREATE DATABASE hstore_test;
\c hstore_test
CREATE EXTENSION hstore WITH SCHEMA public;
CREATE SCHEMA hstore_test_schema;
CREATE TABLE hstore_test_schema.hstore_test_table(
id int,
column1 hstore,
column2 hstore,
PRIMARY KEY( id )
);
CREATE VIEW hstore_test_schema.hstore_test_view AS
SELECT NULLIF(column1, column2) AS comparison FROM hstore_test_schema.hstore_test_table;
为完整起见,转储和恢复过程如下所示:
pg_dump -U xxxx -h localhost -f /tmp/hstore_test_2014-05-12.backup -Fc hstore_test
psql -U xxxx -h localhost -d postgres -c "DROP DATABASE hstore_test"
psql -U xxxx -h localhost -d postgres -c "CREATE DATABASE hstore_test"
pg_restore -U xxxx -h localhost -d hstore_test /tmp/hstore_test_2014-05-12.backup
pg_restore-l/tmp/hstore_test_2014-05-12。备份
建议在创建视图之前启用hstore
扩展:
;
; Archive created at Mon May 12 11:18:32 2014
; dbname: hstore_test
; TOC Entries: 15
; Compression: -1
; Dump Version: 1.12-0
; Format: CUSTOM
; Integer: 4 bytes
; Offset: 8 bytes
; Dumped from database version: 9.3.0
; Dumped by pg_dump version: 9.3.0
;
;
; Selected TOC Entries:
;
2074; 1262 1358002 DATABASE - hstore_test xxxx
7; 2615 1358003 SCHEMA - hstore_test_schema xxxx
5; 2615 2200 SCHEMA - public postgres
2075; 0 0 COMMENT - SCHEMA public postgres
2076; 0 0 ACL - public postgres
173; 3079 11787 EXTENSION - plpgsql
2077; 0 0 COMMENT - EXTENSION plpgsql
174; 3079 1358004 EXTENSION - hstore
2078; 0 0 COMMENT - EXTENSION hstore
171; 1259 1358124 TABLE hstore_test_schema hstore_test_table xxxx
172; 1259 1358132 VIEW hstore_test_schema hstore_test_view xxxx
2069; 0 1358124 TABLE DATA hstore_test_schema hstore_test_table xxxx
1960; 2606 1358131 CONSTRAINT hstore_test_schema hstore_test_table_pkey xxxx
顺便说一句,将NULLIF(col1,col2)
替换为col1=col2
似乎会使错误消失,尽管它是对pg\u restore
所抱怨类型的显式比较。这是一个PostgreSQL错误
在模式中创建表时,pg_dump
正在将search_路径
设置为排除public
。这是正常的。当它转储引用不在搜索路径上的对象时,它会显式地对它们进行模式限定,以便它们工作
它适用于=
情况,因为pg_dump
看到=
在这种情况下实际上是操作符(public.=)
,并以这种形式转储它:
CREATE VIEW hstore_test_view AS
SELECT (hstore_test_table.column1 OPERATOR(public.=) hstore_test_table.column2) AS comparison
FROM hstore_test_table;
但是,pg_dump
无法对通过nullif
伪函数隐式使用的运算符执行此操作。这将导致以下伪命令序列:
CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public;
...
SET search_path = hstore_test_schema, pg_catalog;
...
CREATE VIEW hstore_test_view AS
SELECT NULLIF(hstore_test_table.column1, hstore_test_table.column2) AS comparison
FROM hstore_test_table;
pg_dump
仅使用pg_catalog.pg_get_viewdef
函数转储视图,因此这可能需要服务器后端修复程序
最简单的解决方法是不使用nullif
,而是用更详细但等效的大小写替换它:
CASE WHEN column1 = column2 THEN NULL ELSE column1 END;
语法没有像我们使用显式运算符(public.=)
那样提供模式限定nullif
伪函数运算符的方法,因此修复看起来并不简单
我预计同样的问题会影响到最大的
和最小的
,可能也会影响到不同的
,但事实并非如此。即使在运行时它们不在search\u路径
上,它们似乎也能找到所需的运算符,但如果在视图定义时运算符不在search\u路径上,则不会失败。这表明他们可能正在使用类型的b-tree操作符类,通过目录中的类型条目(通过表的属性找到)来查找操作符。(更新:检查来源,是的,他们就是这么做的)。大概nullif
也应该这样做,但事实并非如此
相反,它死于:
hstore_test=# \set VERBOSITY verbose
hstore_test=# CREATE VIEW hstore_test_schema.hstore_test_view AS
SELECT NULLIF(column1, column2) AS comparison FROM hstore_test_schema.hstore_test_table;
ERROR: 42883: operator does not exist: public.hstore = public.hstore
LINE 2: SELECT NULLIF(column1, column2) AS comparison FROM hstore_te...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
LOCATION: op_error, parse_oper.c:722
当我在那里设置断点时,陷阱位于:
Breakpoint 1, op_error (pstate=pstate@entry=0x1189f38, op=op@entry=0x1189c10, oprkind=oprkind@entry=98 'b', arg1=arg1@entry=97207, arg2=arg2@entry=97207,
fdresult=FUNCDETAIL_NOTFOUND, location=location@entry=58) at parse_oper.c:706
706 {
(gdb) bt
#0 op_error (pstate=pstate@entry=0x1189f38, op=op@entry=0x1189c10, oprkind=oprkind@entry=98 'b', arg1=arg1@entry=97207, arg2=arg2@entry=97207, fdresult=FUNCDETAIL_NOTFOUND,
location=location@entry=58) at parse_oper.c:706
#1 0x000000000051a81b in oper (pstate=pstate@entry=0x1189f38, opname=opname@entry=0x1189c10, ltypeId=ltypeId@entry=97207, rtypeId=rtypeId@entry=97207,
noError=noError@entry=0 '\000', location=location@entry=58) at parse_oper.c:440
#2 0x000000000051ad34 in make_op (pstate=pstate@entry=0x1189f38, opname=0x1189c10, ltree=ltree@entry=0x118a528, rtree=0x118a590, location=58) at parse_oper.c:770
#3 0x00000000005155e1 in transformAExprNullIf (a=0x1189bc0, pstate=0x1189f38) at parse_expr.c:1021
#4 transformExprRecurse (pstate=pstate@entry=0x1189f38, expr=0x1189bc0) at parse_expr.c:244
#5 0x0000000000517484 in transformExpr (pstate=0x1189f38, expr=<optimized out>, exprKind=exprKind@entry=EXPR_KIND_SELECT_TARGET) at parse_expr.c:116
#6 0x000000000051ff30 in transformTargetEntry (pstate=pstate@entry=0x1189f38, node=0x1189bc0, expr=expr@entry=0x0, exprKind=exprKind@entry=EXPR_KIND_SELECT_TARGET,
colname=0x1189ba0 "comparison", resjunk=resjunk@entry=0 '\000') at parse_target.c:94
#7 0x00000000005212df in transformTargetList (pstate=pstate@entry=0x1189f38, targetlist=<optimized out>, exprKind=exprKind@entry=EXPR_KIND_SELECT_TARGET)
at parse_target.c:167
#8 0x00000000004ef594 in transformSelectStmt (stmt=0x11899f0, pstate=0x1189f38) at analyze.c:942
#9 transformStmt (pstate=0x1189f38, parseTree=0x11899f0) at analyze.c:243
#10 0x00000000004f0a2d in parse_analyze (parseTree=0x11899f0,
sourceText=sourceText@entry=0x114e6b0 "CREATE VIEW hstore_test_schema.hstore_test_view AS\nSELECT NULLIF(column1, column2) AS comparison FROM hstore_test_schema.hstore_test_table;", paramTypes=paramTypes@entry=0x0, numParams=numParams@entry=0) at analyze.c:100
#11 0x000000000057cc4e in DefineView (stmt=stmt@entry=0x114f7e8,
queryString=queryString@entry=0x114e6b0 "CREATE VIEW hstore_test_schema.hstore_test_view AS\nSELECT NULLIF(column1, column2) AS comparison FROM hstore_test_schema.hstore_test_table;") at view.c:385
#12 0x000000000065b1cf in ProcessUtilitySlow (parsetree=parsetree@entry=0x114f7e8,
queryString=0x114e6b0 "CREATE VIEW hstore_test_schema.hstore_test_view AS\nSELECT NULLIF(column1, column2) AS comparison FROM hstore_test_schema.hstore_test_table;",
context=<optimized out>, params=params@entry=0x0, completionTag=completionTag@entry=0x7fffc98c9990 "", dest=<optimized out>) at utility.c:1207
#13 0x000000000065a54e in standard_ProcessUtility (parsetree=0x114f7e8, queryString=<optimized out>, context=<optimized out>, params=0x0, dest=<optimized out>,
completionTag=0x7fffc98c9990 "") at utility.c:829
断点1,操作错误(pstate=pstate@entry=0x1189f38,op=op@entry=0x1189c10,oprkind=oprkind@entry=98'b',arg1=arg1@entry=97207,arg2=arg2@entry=97207,
fdresult=FUNCDETAIL\u未找到,位置=location@entry=58)在解析运算c:706
706 {
(gdb)英国电信
#0操作错误(pstate=pstate@entry=0x1189f38,op=op@entry=0x1189c10,oprkind=oprkind@entry=98'b',arg1=arg1@entry=97207,arg2=arg2@entry=97207,fdresult=FUNCDETAIL\u未找到,
位置=location@entry=58)在解析运算c:706
#1 0x000000000051a81b正在运行(pstate=pstate@entry=0x1189f38,opname=opname@entry=0x1189c10,ltypeId=ltypeId@entry=97207,rtypeId=rtypeId@entry=97207,
无误=noError@entry=0'\000',位置=location@entry=58)在解析运算时c:440
#2 0x000000000051ad34在make_op(pstate)中=pstate@entry=0x1189f38,opname=0x1189c10,ltree=ltree@entry=0x118a528,rtree=0x118a590,位置=58)在解析操作c:770
#3解析表达式c:1021处的transformAExprNullIf(a=0x1189bc0,pstate=0x1189f38)中的0x000000000005155E1
#4转换表达式(pstate)=pstate@entry=0x1189f38,expr=0x1189bc0)在解析表达式c:244处
#transformExpr中的5 0x0000000000517484(pstate=0x1189f38,expr=,exprKind=exprKind@entry=EXPR\u KIND\u SELECT\u TARGET)在parse\u EXPR.c:116处
#transformTargetEntry(pstate)中的6 0x000000000051ff30=pstate@entry=0x1189f38,节点=0x1189bc0,expr=expr@entry=0x0,exprKind=exprKind@entry=EXPR\u KIND\u SELECT\u TARGET,
colname=0x1189ba0“比较”,resjunk=resjunk@entry=0'\000'),位于解析_目标。c:94
#transformTargetList(pstate)中的7 0x0000000000521DF=pstate@entry=0x1189f38,targetlist=,exprKind=exprKind@entry=EXPR\u种类\u选择\u目标)
在parse_target.c:167
#在analyze.c:942处的transformSelectStmt(stmt=0x11899f0,pstate=0x1189f38)中的8 0x00000000004ef594
#位于analyze.c:243的9 transformStmt(pstate=0x1189f38,parseTree=0x11899f0)
#解析分析中的10 0x00000000004f0a2d(解析树=0x11899f0,
源文本=sourceText@entry=0x114e6b0“创建视图hstore_test_schema.hstore_test_VIEW AS\n从hstore_test_schema.hstore_test_table;中选择NULLIF(第1列,第2列)作为比较”,参数类型=paramTypes@entry=0x0,numParams=numParams@entry=0)在分析时。c:100
#定义视图中的11 0x000000000057cc4e(stmt=stmt@entry=0x114f7e8,
质询=queryString@entry=0x114e6b0“创建视图hstore_test_schema.hstore_test_VIEW AS\n选择NULLIF(第1列、第2列)作为与视图中hstore_test_schema.hstore_test_table;的比较”)。c:385
#ProcessUtilitySlow(parsetree)中的12 0x000000000065b1cf=parsetree@entry=0x114f7e8,
queryString=0x114e6b0“创建视图hstore_测试_架构。hstore_测试_视图作为\n从hstore_测试_架构。hstore_测试_表格中选择NULLIF(第1列,第2列)作为比较;”,
上下文=,参数=params@entry=0x0,completionTag=completionTag@entry=0x7fffc98c9990“”,目标=)位于实用程序c:1207
#13标准_ProcessUtility中的0x000000000065a54e(语法树=0x114f7e8,查询字符串=,上下文=,参数=0x0,目的地=,
completionTag=0x7fffc98c9990“”),位于utility.c:829
因此,眼前的问题看起来像是transformAExprNullIf
无法通过b-树opclass和typecache使用操作数类型查找运算符。我现在提出的是pgsql错误。非常有趣,您的解决方法非常有效,谢谢。2019,导出时错误仍然存在