- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个自定义类型 gp
来模拟 DND 5e 货币系统。我在 gp.c
中定义了自定义输入和输出函数:
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include <stdio.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
static const char* inputFormat = " %i %s2 ";
static const char* invalidFormat = "invalid input syntax for gp: \"%s\"";
PG_FUNCTION_INFO_V1(gp_input);
Datum gp_input(PG_FUNCTION_ARGS) {
char* raw = PG_GETARG_CSTRING(0);
int32 amt;
char unit[3];
if (sscanf(raw, inputFormat, &amt, &unit[0]) != 2) {
ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg(invalidFormat, raw)));
}
switch(unit[1]) {
case 'p':
break;
default:
ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg(invalidFormat, raw)));
}
switch(unit[0]) {
case 'c':
break;
case 's':
amt *= 10;
break;
case 'e':
amt *= 50;
break;
case 'g':
amt *= 100;
break;
case 'p':
amt *= 1000;
break;
default:
ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg(invalidFormat, raw)));
}
int32* result = (int32*)palloc(sizeof(int32));
*result = amt;
PG_RETURN_POINTER(result);
}
PG_FUNCTION_INFO_V1(gp_output);
Datum gp_output(PG_FUNCTION_ARGS) {
int32* raw = (int32*)PG_GETARG_POINTER(0);
int32 val = *raw;
unsigned int bufsz = sizeof(unsigned char)*9 + 2;// allow up to 999999999[pgsc]p
char* buf = (char*) palloc(bufsz+1); // +1 b/c '\0'
if (val >= 10 && val % 10 == 0) {
val /= 10;
if (val >= 10 && val % 10 == 0) {
val /= 10;
if (val >= 10 && val % 10 == 0) {
val /= 10;
if (sprintf(buf, "%dpp", val) <= 0) {
ereport(ERROR, (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), errmsg("Bad value for gp")));
}
}
else {
if (sprintf(buf, "%dgp", val) <= 0) {
ereport(ERROR, (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), errmsg("Bad value for gp")));
}
}
}
else {
if (sprintf(buf, "%dsp", val) <= 0) {
ereport(ERROR, (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), errmsg("Bad value for gp")));
}
}
}
else {
if (sprintf(buf, "%dcp", val) <= 0) {
ereport(ERROR, (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER), errmsg("Bad value for gp")));
}
}
PG_RETURN_CSTRING(buf);
}
我知道我没有检查数字是否超出范围或存储的值是否适合缓冲区,但我还没有遇到那个问题。我的问题是 postgres 似乎正在编辑,在某些情况下会破坏我正在存储的值。我有这个测试 SQL 文件:
DROP TYPE IF EXISTS gp CASCADE;
DROP TABLE IF EXISTS test;
CREATE TYPE gp;
CREATE FUNCTION gp_input(cstring) RETURNS gp AS '$libdir/gp.so' LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gp_output(gp) RETURNS cstring AS '$libdir/gp.so' LANGUAGE C IMMUTABLE STRICT;
CREATE TYPE gp (input=gp_input, output=gp_output);
CREATE TABLE test (val gp);
INSERT INTO test VALUES ('12sp'), ('100gp'), ('1000cp'), ('101cp');
SELECT * FROM test;
INSERT INTO test VALUES ('101sp');
SELECT
的输出是:
val
-------
12sp
10pp
1pp
212cp
(4 rows)
所以我们可以看到除了最后一个值外,所有值都被正确存储和表示:101cp
被存储为指向 int32
值 212
。使用 ereport
警告,我能够确定在输入函数返回之前,result
指向正确的值:101
。但是,作为参数传递给我的输出函数的指针指向一个我没有存储的值:212
。在输入代码结尾和输出代码开头之间的某处,postgres 损坏了该值。这总是发生在输入字符串 101cp
上,与表的状态或同时插入的任何其他值无关。
但是现在真正奇怪的部分是;最后一个 INSERT
使客户端崩溃。解析该 gp 值后,它会打印错误:
psql:./gptest.sql:15: ERROR: compressed data is corrupted
LINE 1: INSERT INTO test VALUES ('101sp');
^
这总是发生在值 101sp
上,无论表状态或任何其他值与它一起插入。使用 ereport
警告,我能够在 return 语句之前看到,result
指向正确的值:1010
。这也意味着崩溃发生在返回宏扩展或某些底层代码中。
所以我真的不知道发生了什么。我正在做 palloc
所以不允许覆盖内存,而且我想不出包含 101
的值总是有问题的任何原因 - 以及不同的问题取决于单位。 int32
应该能够存储我正在测试的小值,但事实并非如此。我不知道这是否应该是这样实现的,但我已经检查过并且传递给输出的指针与这些值中的任何一个的 result
指针的地址不同,所以我假设它在幕后错误地执行了某种memcpy
,但随后我知道如何期望任何人定义自定义基本数据类型。
最佳答案
CREATE TYPE
采用大量可选参数,其中一些与数据的物理布局有关,并且这些参数需要与您的 I/O 函数期望/返回的结构一致。
文档似乎没有提到这些参数的默认值,但是提到“压缩数据”的错误表明您的值是 TOASTed ,即 INTERNALLENGTH
默认为 VARIABLE
。此类类型应以描述值的总长度的 varlena
header 开头,这肯定不是您要返回的内容(尽管 Postgres 仍会这样解释它,从而导致各种奇怪的情况行为,更不用说将大量随机字节保存到您的表中,并且迟早会出现段错误......)。
如果您的目标是创建一个在内部表示为简单整数(固定长度、按值传递等)的类型,您可以只复制内置类型的特征:
CREATE TYPE gp (input=gp_input, output=gp_output, like=integer);
然后您应该能够取消 palloc()
和指针,使用 PG_GETARG_INT32(0)
获取您的参数,然后返回 PG_RETURN_INT32 (amt)
。
如果您想要内置类型的所有行为,但使用自定义显示格式,这比您预期的要容易得多。
numeric
之类的内部 C 例程与您为自己实现此类类型而编写的例程相同。因此,您只需复制粘贴其 SQL 级别的定义,然后让指向现有 C 处理程序的函数完成所有实际工作,即可创建您自己的此类内置类型版本:
CREATE TYPE gp;
CREATE FUNCTION gp_in(cstring,oid,integer) RETURNS gp LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numeric_in';
CREATE FUNCTION gp_out(gp) RETURNS cstring LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numeric_out';
CREATE FUNCTION gp_send(gp) RETURNS bytea LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numeric_send';
CREATE FUNCTION gp_recv(internal,oid,integer) RETURNS gp LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numeric_recv';
CREATE FUNCTION gptypmodin(cstring[]) RETURNS integer LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numerictypmodin';
CREATE FUNCTION gptypmodout(integer) RETURNS cstring LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE AS 'numerictypmodout';
CREATE TYPE gp (
INPUT = gp_in,
OUTPUT = gp_out,
RECEIVE = gp_recv,
SEND = gp_send,
TYPMOD_IN = gptypmodin,
TYPMOD_OUT = gptypmodout,
LIKE = numeric
);
CREATE TABLE t (x gp(10,2), y gp);
INSERT INTO t VALUES ('123.45', '2387456987623498765324.2837654987364987269837456981');
SELECT * FROM t;
x | y
--------+-----------------------------------------------------
123.45 | 2387456987623498765324.2837654987364987269837456981
从那里,您可以用您自己的 C 函数替换输入/输出处理程序,从 internal functions 复制粘贴代码作为起点。在您的情况下,最简单的方法可能是在函数开头将 DnD 货币字符串转换为简单的十进制字符串,并让其余代码担心将其转换为 Numeric
.
如果你想要算术/比较运算符、索引操作类、最小/最大聚合、类型转换等,你也可以从原始类型复制粘贴这些定义,只要你不弄乱内部二进制格式。
关于c - 自定义基本数据类型的输入函数中的 Postgresql 损坏数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54674045/
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!