issue修复:ignore插入时,若插入值类型与目标类型无转换规则,目标类型的默认零值无法被插入的问题修复
This commit is contained in:
@ -1356,6 +1356,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt)
|
||||
|
||||
qry->commandType = CMD_INSERT;
|
||||
pstate->p_is_insert = true;
|
||||
pstate->p_has_ignore = stmt->hasIgnore;
|
||||
/* set io state for backend status for the thread, we will use it to check user space */
|
||||
pgstat_set_io_state(IOSTATE_WRITE);
|
||||
|
||||
@ -3325,6 +3326,7 @@ static Query* transformUpdateStmt(ParseState* pstate, UpdateStmt* stmt)
|
||||
|
||||
qry->commandType = CMD_UPDATE;
|
||||
pstate->p_is_insert = false;
|
||||
pstate->p_has_ignore = stmt->hasIgnore;
|
||||
|
||||
/* set io state for backend status for the thread, we will use it to check user space */
|
||||
pgstat_set_io_state(IOSTATE_READ);
|
||||
|
@ -58,6 +58,7 @@ ParseState* make_parsestate(ParseState* parentParseState)
|
||||
pstate->ignoreplus = false;
|
||||
pstate->p_plusjoin_rte_info = NULL;
|
||||
pstate->p_rawdefaultlist = NIL;
|
||||
pstate->p_has_ignore = false;
|
||||
|
||||
if (parentParseState != NULL) {
|
||||
pstate->p_sourcetext = parentParseState->p_sourcetext;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "utils/rel.h"
|
||||
#include "utils/rel_gs.h"
|
||||
#include "utils/typcache.h"
|
||||
#include "executor/executor.h"
|
||||
#include "gs_ledger/ledger_utils.h"
|
||||
|
||||
static void markTargetListOrigin(ParseState* pstate, TargetEntry* tle, Var* var, int levelsup);
|
||||
@ -513,17 +514,24 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, char* colname, int a
|
||||
colname, format_type_be(attrtype), format_type_be(type_id)),
|
||||
errhint("You will need to rewrite or cast the expression."),
|
||||
parser_errposition(pstate, exprLocation(orig_expr))));
|
||||
} else {
|
||||
if (!pstate->p_has_ignore) {
|
||||
ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("column \"%s\" is of type %s"
|
||||
" but expression is of type %s",
|
||||
colname, format_type_be(attrtype), format_type_be(type_id)),
|
||||
errhint("You will need to rewrite or cast the expression."),
|
||||
parser_errposition(pstate, exprLocation(orig_expr))));
|
||||
}
|
||||
expr = (Expr*)makeConst(attrtype, attrtypmod, attrcollation, rd->rd_att->attrs[attrno - 1]->attlen,
|
||||
GetTypeZeroValue(rd->rd_att->attrs[attrno - 1]), false,
|
||||
rd->rd_att->attrs[attrno - 1]->attbyval);
|
||||
ereport(WARNING, (errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("column \"%s\" is of type %s"
|
||||
" but expression is of type %s. Data truncated automatically.",
|
||||
colname, format_type_be(attrtype), format_type_be(type_id))));
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("column \"%s\" is of type %s"
|
||||
" but expression is of type %s",
|
||||
colname,
|
||||
format_type_be(attrtype),
|
||||
format_type_be(type_id)),
|
||||
errhint("You will need to rewrite or cast the expression."),
|
||||
parser_errposition(pstate, exprLocation(orig_expr))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ELOG_FIELD_NAME_END;
|
||||
|
@ -2438,9 +2438,9 @@ void PthreadRwLockInit(pthread_rwlock_t* rwlock, pthread_rwlockattr_t *attr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get defaulted value of specific time type
|
||||
* Get defaulted value of specific type
|
||||
*/
|
||||
static Datum GetTimeTypeZeroValue(Form_pg_attribute att_tup)
|
||||
Datum GetTypeZeroValue(Form_pg_attribute att_tup)
|
||||
{
|
||||
Datum result;
|
||||
switch (att_tup->atttypid) {
|
||||
@ -2473,21 +2473,10 @@ static Datum GetTimeTypeZeroValue(Form_pg_attribute att_tup)
|
||||
smalldatetime_in, CStringGetDatum("1970-01-01 08:00:00"), ObjectIdGetDatum(0), Int32GetDatum(-1));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
case DATEOID: {
|
||||
result = timestamp2date(SetEpochTimestamp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get defaulted value of specific non-time type
|
||||
*/
|
||||
static Datum GetNotTimeTypeZeroValue(Form_pg_attribute att_tup)
|
||||
{
|
||||
Datum result;
|
||||
switch (att_tup->atttypid) {
|
||||
case UUIDOID: {
|
||||
result = (Datum)DirectFunctionCall3(uuid_in, CStringGetDatum("00000000-0000-0000-0000-000000000000"),
|
||||
ObjectIdGetDatum(0), Int32GetDatum(-1));
|
||||
@ -2576,15 +2565,7 @@ Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot *slot)
|
||||
int attrChk;
|
||||
for (attrChk = 1; attrChk <= natts; attrChk++) {
|
||||
if (tupleDesc->attrs[attrChk - 1]->attnotnull && tableam_tslot_attisnull(slot, attrChk)) {
|
||||
bool isTimeType = (tupleDesc->attrs[attrChk - 1]->atttypid == DATEOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == TIMESTAMPOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == TIMESTAMPTZOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == TIMETZOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == INTERVALOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == TINTERVALOID ||
|
||||
tupleDesc->attrs[attrChk - 1]->atttypid == SMALLDATETIMEOID);
|
||||
values[attrChk - 1] = isTimeType ? GetTimeTypeZeroValue(tupleDesc->attrs[attrChk - 1])
|
||||
: GetNotTimeTypeZeroValue(tupleDesc->attrs[attrChk - 1]);
|
||||
values[attrChk - 1] = GetTypeZeroValue(tupleDesc->attrs[attrChk - 1]);
|
||||
replaces[attrChk - 1] = true;
|
||||
}
|
||||
}
|
||||
|
@ -466,6 +466,7 @@ extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, TupleTa
|
||||
FakeRelationPartition *relAndPart);
|
||||
extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd);
|
||||
extern void GetFakeRelAndPart(EState *estate, Relation rel, TupleTableSlot *slot, FakeRelationPartition *relAndPart);
|
||||
extern Datum GetTypeZeroValue(Form_pg_attribute att_tup);
|
||||
extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot);
|
||||
|
||||
// AutoMutexLock
|
||||
|
@ -189,6 +189,7 @@ struct ParseState {
|
||||
List *sw_fromClause;
|
||||
WithClause *origin_with;
|
||||
bool p_hasStartWith;
|
||||
bool p_has_ignore; /* whether SQL has ignore hint */
|
||||
|
||||
/*
|
||||
* Optional hook functions for parser callbacks. These are null unless
|
||||
|
@ -791,5 +791,123 @@ select * from t_int;
|
||||
12
|
||||
(1 row)
|
||||
|
||||
-- test for inconvertible type transform.
|
||||
drop table if exists t_int;
|
||||
create table t_int(num int);
|
||||
insert /*+ ignore_error */ into t_int values('2011-8-2'::timestamp);
|
||||
WARNING: column "num" is of type integer but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: num
|
||||
select * from t_int;
|
||||
num
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
delete from t_int;
|
||||
drop table if exists t_timestamp;
|
||||
NOTICE: table "t_timestamp" does not exist, skipping
|
||||
create table t_timestamp(val timestamp);
|
||||
insert into t_timestamp values('2011-8-2');
|
||||
insert /*+ ignore_error */ into t_int select val from t_timestamp;
|
||||
WARNING: column "num" is of type integer but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: num
|
||||
select * from t_int;
|
||||
num
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
delete from t_int;
|
||||
insert into t_int values(999);
|
||||
update /*+ ignore_error */ t_int set num = '2011-8-2'::timestamp;
|
||||
WARNING: column "num" is of type integer but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: num
|
||||
select * from t_int;
|
||||
num
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
drop table if exists t_multi;
|
||||
NOTICE: table "t_multi" does not exist, skipping
|
||||
create table t_multi(c1 int unique, c2 int);
|
||||
NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_multi_c1_key" for table "t_multi"
|
||||
insert /*+ ignore_error */ into t_multi values('2011-8-2'::timestamp, 1);
|
||||
WARNING: column "c1" is of type integer but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: c1
|
||||
insert /*+ ignore_error */ into t_multi values(0, 0) on duplicate key update c2 = 2;
|
||||
select * from t_multi;
|
||||
c1 | c2
|
||||
----+----
|
||||
0 | 2
|
||||
(1 row)
|
||||
|
||||
insert /*+ ignore_error */ into t_multi values('2011-8-2'::timestamp , 3) on duplicate key update c2 = 3;
|
||||
WARNING: column "c1" is of type integer but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: c1
|
||||
select * from t_multi;
|
||||
c1 | c2
|
||||
----+----
|
||||
0 | 3
|
||||
(1 row)
|
||||
|
||||
drop table if exists t_float8;
|
||||
NOTICE: table "t_float8" does not exist, skipping
|
||||
create table t_float8(num float8);
|
||||
insert /*+ ignore_error */ into t_float8 values('2011-8-2'::timestamp);
|
||||
WARNING: column "num" is of type double precision but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: num
|
||||
select * from t_float8;
|
||||
num
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
delete from t_float8;
|
||||
insert into t_float8 values(123.999);
|
||||
update /*+ ignore_error */ t_float8 set num = '2011-8-2'::timestamp;
|
||||
WARNING: column "num" is of type double precision but expression is of type timestamp without time zone. Data truncated automatically.
|
||||
CONTEXT: referenced column: num
|
||||
select * from t_float8;
|
||||
num
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
drop table if exists t_uuid;
|
||||
NOTICE: table "t_uuid" does not exist, skipping
|
||||
create table t_uuid(val uuid);
|
||||
insert /*+ ignore_error */ into t_uuid values(0);
|
||||
WARNING: column "val" is of type uuid but expression is of type integer. Data truncated automatically.
|
||||
CONTEXT: referenced column: val
|
||||
select * from t_uuid;
|
||||
val
|
||||
--------------------------------------
|
||||
00000000-0000-0000-0000-000000000000
|
||||
(1 row)
|
||||
|
||||
drop table if exists t_date;
|
||||
NOTICE: table "t_date" does not exist, skipping
|
||||
create table t_date(val date);
|
||||
insert /*+ ignore_error */ into t_date values(0);
|
||||
WARNING: column "val" is of type date but expression is of type integer. Data truncated automatically.
|
||||
CONTEXT: referenced column: val
|
||||
select * from t_date;
|
||||
val
|
||||
------------
|
||||
01-01-1970
|
||||
(1 row)
|
||||
|
||||
delete from t_date;
|
||||
insert into t_date values('2011-8-2');
|
||||
update /*+ ignore_error */ t_date set val = 0;
|
||||
WARNING: column "val" is of type date but expression is of type integer. Data truncated automatically.
|
||||
CONTEXT: referenced column: val
|
||||
select * from t_date;
|
||||
val
|
||||
------------
|
||||
01-01-1970
|
||||
(1 row)
|
||||
|
||||
\c postgres
|
||||
drop database if exists sql_ignore_type_transform_test;
|
||||
|
@ -342,5 +342,56 @@ create table t_int(num int);
|
||||
insert /*+ ignore_error */ into t_int values('12a34');
|
||||
select * from t_int;
|
||||
|
||||
-- test for inconvertible type transform.
|
||||
drop table if exists t_int;
|
||||
create table t_int(num int);
|
||||
insert /*+ ignore_error */ into t_int values('2011-8-2'::timestamp);
|
||||
select * from t_int;
|
||||
|
||||
delete from t_int;
|
||||
drop table if exists t_timestamp;
|
||||
create table t_timestamp(val timestamp);
|
||||
insert into t_timestamp values('2011-8-2');
|
||||
insert /*+ ignore_error */ into t_int select val from t_timestamp;
|
||||
select * from t_int;
|
||||
|
||||
delete from t_int;
|
||||
insert into t_int values(999);
|
||||
update /*+ ignore_error */ t_int set num = '2011-8-2'::timestamp;
|
||||
select * from t_int;
|
||||
|
||||
drop table if exists t_multi;
|
||||
create table t_multi(c1 int unique, c2 int);
|
||||
insert /*+ ignore_error */ into t_multi values('2011-8-2'::timestamp, 1);
|
||||
insert /*+ ignore_error */ into t_multi values(0, 0) on duplicate key update c2 = 2;
|
||||
select * from t_multi;
|
||||
insert /*+ ignore_error */ into t_multi values('2011-8-2'::timestamp , 3) on duplicate key update c2 = 3;
|
||||
select * from t_multi;
|
||||
|
||||
drop table if exists t_float8;
|
||||
create table t_float8(num float8);
|
||||
insert /*+ ignore_error */ into t_float8 values('2011-8-2'::timestamp);
|
||||
select * from t_float8;
|
||||
|
||||
delete from t_float8;
|
||||
insert into t_float8 values(123.999);
|
||||
update /*+ ignore_error */ t_float8 set num = '2011-8-2'::timestamp;
|
||||
select * from t_float8;
|
||||
|
||||
drop table if exists t_uuid;
|
||||
create table t_uuid(val uuid);
|
||||
insert /*+ ignore_error */ into t_uuid values(0);
|
||||
select * from t_uuid;
|
||||
|
||||
drop table if exists t_date;
|
||||
create table t_date(val date);
|
||||
insert /*+ ignore_error */ into t_date values(0);
|
||||
select * from t_date;
|
||||
|
||||
delete from t_date;
|
||||
insert into t_date values('2011-8-2');
|
||||
update /*+ ignore_error */ t_date set val = 0;
|
||||
select * from t_date;
|
||||
|
||||
\c postgres
|
||||
drop database if exists sql_ignore_type_transform_test;
|
Reference in New Issue
Block a user