我已经为如下数据类型创建了一个输入函数:
mytimestamp(X)
Postgres文档指出,在这种情况下,当调用输入函数时,类型修饰符将作为第三个参数传递给函数。然而,在我的情况下,类型修饰符总是为-1,这没有意义。下面的命令:
select atttypid,atttypmod
from pq_attribute
where attname='mytimestamp';
显示类型已创建,atttypmod值也是我所期望的。然而,input函数仍然显示类型修饰符为-1。我也尝试使用getBaseTypeAndTypmod函数,但它也返回了类型修饰符-1。我完全不知道下一步该怎么做才能解决这个问题。
这和我定义类型的方式有什么关系吗?
create type mytimestamp
(
INPUT = mytimestampin,
OUTPUT = mytimestampout,
RECEIVE = mytimestamprecv,
SEND = mytimestampsend,
TYPEMOD_IN = mytimestamptypmodin,
-- TYPEMOD_OUT = mytimestamptypmodout,
STORAGE = extended,
CATEGORY = 'd',
PREFERRED = true
);
并且函数被定义为:
CREATE OR REPLACE FUNCTION mytimestampin(cstring, oid, int4) RETURNS mytimestamp
AS '$libdir/libmy_pgmod', 'mytimestampin'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION mytimestampout(mytimestamp) RETURNS cstring
AS '$libdir/libmy_pgmod', 'mytimestampout'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION mytimestamprecv(internal, oid, int4) RETURNS mytimestamp
AS '$libdir/libmy_pgmod', 'mytimestamprecv'
LANGUAGE C STABLE STRICT;
CREATE OR REPLACE FUNCTION mytimestampsend(mytimestamp) RETURNS bytea
AS '$libdir/libmy_pgmod', 'mytimestampsend'
LANGUAGE C STABLE STRICT;
CREATE OR REPLACE FUNCTION mytimestamptypmodin(cstring[]) RETURNS int4
AS '$libdir/libmy_pgmod', 'mytimestamptypmodin'
LANGUAGE C IMMUTABLE STRICT;
--CREATE OR REPLACE FUNCTION mytimestamptypmodout(int4) RETURNS cstring
-- AS '$libdir/libmy_pgmod', 'mytimestamptypmodout'
-- LANGUAGE C IMMUTABLE STRICT;
我不能把完整的代码放在这里,但是,这里是开始:
PG_FUNCTION_INFO_V1(mytimestampin);
...
Datum mytimestampin( PG_FUNCTION_ARGS ) {
const char *pszTS = PG_GETARG_CSTRING( 0 );
uint32_t atttypmod = PG_GETARG_INT32( 2 );
struct varlena *result = NULL;
PAPrSqBs_t pTimestamp = NULL;
PAPrSqCl_t pCol = NULL;
int64_t width = 0;
int length = 0;
unsigned char *pOut = NULL;
int32_t precision = -1;
PAPrSqRcInit( );
pTimestamp = PAPrSqBs_new( timestamp );
pCol = PAPrSqCl_new( timestamp );
/**
* Get the precision.
*/
if ( (uint32_t)-1 == atttypmod ) {
precision = PAPrSqCl_getPrecision( pCol, max );
} else {
precision = atttypmod;
}
...
/**
* Destroy the column and timestamp types.
*/
PAPrSqCl_delete( pCol );
PAPrSqBs_delete( pTimestamp );
PAPrSqRcClean( );
PG_RETURN_POINTER( result );
}
查询请求的结果如下:
attname | atttypid | atttypmod
---------+-------------+-----------
TS | mytimestamp | 6
CHAR10 | mychar | 656506
VCHAR20 | myvarchar | 1311866
FB31 | integer | -1
FB15 | smallint | -1
DT | mydate | -1
TM | mytime | -1
(7 rows)
1条答案
按热度按时间vsmadaxz1#
简短回答
您需要:
说明
你需要一个从你的类型到...相同类型的强制转换函数,带有一个类型修饰符;如果您希望在初始输入之后的某个时间点应用/强制修改器,这是必要的。
假设
SELECT '2016-09-06-15.24.35.123456' ::mytimestamp(8)
将:mytimestampin
,但您得到是:
mytimestampin
,后跟如果没有提供这样的自投,它将只是耸耸肩。
这实际上并不是一个与类型定义(或
mytimestampin
)相关的问题,而是一个假设,即您必须至少提供一些类型转换,才能使您的类型像内置函数一样可用。参考
PostgreSQL Documentation: Reference / SQL Commands / CREATE CAST — define a new cast
通常,转换必须具有不同的源数据类型和目标数据类型。但是,如果转换的转换实现函数具有多个参数,则允许使用相同的源数据类型和目标数据类型声明转换。这用于表示系统目录中特定于类型的长度强制转换函数。命名函数用于将类型的值强制转换为由其第二个参数给定的类型修饰符值。
当转换具有不同的源类型和目标类型以及采用多个参数的函数时,它支持在一个步骤中从一种类型转换为另一种类型并应用长度强制。当没有这样的条目时,对使用类型修饰符的类型的强制涉及两个转换步骤,一个步骤用于在数据类型之间转换,另一个步骤用于应用修饰符。