diff --git a/src/bin/gs_guc/cluster_guc.conf b/src/bin/gs_guc/cluster_guc.conf index d23e9b7bd..c8fccdaa1 100755 --- a/src/bin/gs_guc/cluster_guc.conf +++ b/src/bin/gs_guc/cluster_guc.conf @@ -267,6 +267,7 @@ hot_standby_feedback|bool|0,0|NULL|NULL| ident_file|string|0,0|NULL|NULL| ignore_checksum_failure|bool|0,0|NULL|Continues processing after a checksum failure.| ignore_system_indexes|bool|0,0|NULL|When ignore_system_indexes set to on, it is very useful for recovering data from the table which system index is corrupted.| +sql_ignore_strategy|string|0,0|NULL|NULL| parctl_min_cost|int|-1,2147483647|NULL|NULL| io_control_unit|int|1000,1000000|NULL|NULL| gin_pending_list_limit|int|64,2147483647|kB|NULL| diff --git a/src/common/backend/catalog/heap.cpp b/src/common/backend/catalog/heap.cpp index 20f8f2519..a72f5c294 100644 --- a/src/common/backend/catalog/heap.cpp +++ b/src/common/backend/catalog/heap.cpp @@ -7125,7 +7125,7 @@ int lookupHBucketid(oidvector *buckets, int low, int2 bktId) * Description : * Notes : */ -Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL) +Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL, bool canIgnore) { Oid partitionid = InvalidOid; @@ -7143,31 +7143,35 @@ Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL) * feedback for non-existing table partition. * If the routing result indicates a range partition, give error report */ + int level = canIgnore ? WARNING : ERROR; switch (u_sess->catalog_cxt.route->partArea) { /* * If it is a range partition, give error report */ case PART_AREA_RANGE: { - ereport(ERROR, + ereport( + level, (errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition"))); } break; case PART_AREA_INTERVAL: { return AddNewIntervalPartition(rel, tuple, isDDL); } break; case PART_AREA_LIST: { - ereport(ERROR, + ereport( + level, (errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition"))); } break; case PART_AREA_HASH: { - ereport(ERROR, + ereport( + level, (errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition"))); } break; /* never happen; just to be self-contained */ default: { - ereport(ERROR, - (errcode(ERRCODE_NO_DATA_FOUND), - errmsg("Inserted partition key does not map to any table partition"), - errdetail("Unrecognized PartitionArea %d", u_sess->catalog_cxt.route->partArea))); + ereport( + level, + (errcode(ERRCODE_NO_DATA_FOUND), errmsg("Inserted partition key does not map to any table partition"), + errdetail("Unrecognized PartitionArea %d", u_sess->catalog_cxt.route->partArea))); } break; } diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 6c0270bc9..ccd6ac137 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -125,6 +125,7 @@ static PlannedStmt* _copyPlannedStmt(const PlannedStmt* from) COPY_SCALAR_FIELD(queryId); COPY_SCALAR_FIELD(hasReturning); COPY_SCALAR_FIELD(hasModifyingCTE); + COPY_SCALAR_FIELD(hasIgnore); COPY_SCALAR_FIELD(canSetTag); COPY_SCALAR_FIELD(transientPlan); COPY_SCALAR_FIELD(dependsOnRole); @@ -4543,6 +4544,7 @@ static Query* _copyQuery(const Query* from) COPY_SCALAR_FIELD(hasForUpdate); COPY_SCALAR_FIELD(hasRowSecurity); COPY_SCALAR_FIELD(hasSynonyms); + COPY_SCALAR_FIELD(hasIgnore); COPY_NODE_FIELD(cteList); COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(jointree); @@ -4601,6 +4603,7 @@ static InsertStmt* _copyInsertStmt(const InsertStmt* from) COPY_NODE_FIELD(upsertClause); COPY_NODE_FIELD(hintState); COPY_SCALAR_FIELD(isRewritten); + COPY_SCALAR_FIELD(hasIgnore); return newnode; } @@ -4630,6 +4633,7 @@ static UpdateStmt* _copyUpdateStmt(const UpdateStmt* from) COPY_NODE_FIELD(returningList); COPY_NODE_FIELD(withClause); COPY_NODE_FIELD(hintState); + COPY_SCALAR_FIELD(hasIgnore); return newnode; } diff --git a/src/common/backend/nodes/equalfuncs.cpp b/src/common/backend/nodes/equalfuncs.cpp index 6cfe83dcb..c4bcfa364 100644 --- a/src/common/backend/nodes/equalfuncs.cpp +++ b/src/common/backend/nodes/equalfuncs.cpp @@ -845,6 +845,7 @@ static bool _equalQuery(const Query* a, const Query* b) COMPARE_SCALAR_FIELD(hasForUpdate); COMPARE_SCALAR_FIELD(hasRowSecurity); COMPARE_SCALAR_FIELD(hasSynonyms); + COMPARE_SCALAR_FIELD(hasIgnore); COMPARE_NODE_FIELD(cteList); COMPARE_NODE_FIELD(rtable); COMPARE_NODE_FIELD(jointree); @@ -892,6 +893,7 @@ static bool _equalInsertStmt(const InsertStmt* a, const InsertStmt* b) COMPARE_NODE_FIELD(returningList); COMPARE_NODE_FIELD(withClause); COMPARE_NODE_FIELD(upsertClause); + COMPARE_SCALAR_FIELD(hasIgnore); return true; } @@ -916,6 +918,7 @@ static bool _equalUpdateStmt(const UpdateStmt* a, const UpdateStmt* b) COMPARE_NODE_FIELD(fromClause); COMPARE_NODE_FIELD(returningList); COMPARE_NODE_FIELD(withClause); + COMPARE_SCALAR_FIELD(hasIgnore); return true; } diff --git a/src/common/backend/nodes/outfuncs.cpp b/src/common/backend/nodes/outfuncs.cpp index dbb4adb3d..08b7e9a01 100755 --- a/src/common/backend/nodes/outfuncs.cpp +++ b/src/common/backend/nodes/outfuncs.cpp @@ -528,6 +528,9 @@ static void _outPlannedStmt(StringInfo str, PlannedStmt* node) WRITE_UINT64_FIELD(queryId); WRITE_BOOL_FIELD(hasReturning); WRITE_BOOL_FIELD(hasModifyingCTE); + if (t_thrd.proc->workingVersionNum >= KEYWORD_IGNORE_COMPART_VERSION_NUM) { + WRITE_BOOL_FIELD(hasIgnore); + } WRITE_BOOL_FIELD(canSetTag); WRITE_BOOL_FIELD(transientPlan); WRITE_BOOL_FIELD(dependsOnRole); @@ -3674,6 +3677,9 @@ static void _outInsertStmt(StringInfo str, InsertStmt* node) WRITE_NODE_FIELD(upsertClause); #endif WRITE_NODE_FIELD(hintState); + if (t_thrd.proc->workingVersionNum >= KEYWORD_IGNORE_COMPART_VERSION_NUM) { + WRITE_BOOL_FIELD(hasIgnore); + } } static void _outUpdateStmt(StringInfo str, UpdateStmt* node) @@ -3687,6 +3693,9 @@ static void _outUpdateStmt(StringInfo str, UpdateStmt* node) WRITE_NODE_FIELD(returningList); WRITE_NODE_FIELD(withClause); WRITE_NODE_FIELD(hintState); + if (t_thrd.proc->workingVersionNum >= KEYWORD_IGNORE_COMPART_VERSION_NUM) { + WRITE_BOOL_FIELD(hasIgnore); + } } static void _outSelectStmt(StringInfo str, SelectStmt* node) @@ -4315,6 +4324,9 @@ static void _outQuery(StringInfo str, Query* node) if (t_thrd.proc->workingVersionNum >= SYNONYM_VERSION_NUM) { WRITE_BOOL_FIELD(hasSynonyms); } + if (t_thrd.proc->workingVersionNum >= KEYWORD_IGNORE_COMPART_VERSION_NUM) { + WRITE_BOOL_FIELD(hasIgnore); + } WRITE_NODE_FIELD(cteList); WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(jointree); diff --git a/src/common/backend/nodes/readfuncs.cpp b/src/common/backend/nodes/readfuncs.cpp index fa90dc7c5..232fefb3f 100755 --- a/src/common/backend/nodes/readfuncs.cpp +++ b/src/common/backend/nodes/readfuncs.cpp @@ -1421,6 +1421,9 @@ static Query* _readQuery(void) IF_EXIST(hasSynonyms) { READ_BOOL_FIELD(hasSynonyms); } + IF_EXIST(hasIgnore) { + READ_BOOL_FIELD(hasIgnore); + } READ_NODE_FIELD(cteList); READ_NODE_FIELD(rtable); READ_NODE_FIELD(jointree); @@ -4254,6 +4257,9 @@ static PlannedStmt* _readPlannedStmt(void) READ_UINT64_FIELD(queryId); READ_BOOL_FIELD(hasReturning); READ_BOOL_FIELD(hasModifyingCTE); + IF_EXIST(hasIgnore) { + READ_BOOL_FIELD(hasIgnore); + } READ_BOOL_FIELD(canSetTag); READ_BOOL_FIELD(transientPlan); IF_EXIST(dependsOnRole) { diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 2baa41849..d81276cc9 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -1875,6 +1875,7 @@ static Query* transformInsertStmt(ParseState* pstate, InsertStmt* stmt) /* Set query tdTruncCastStatus to recored if auto truncation enabled or not. */ qry->tdTruncCastStatus = pstate->tdTruncCastStatus; qry->hintState = stmt->hintState; + qry->hasIgnore = stmt->hasIgnore; return qry; } @@ -3429,6 +3430,7 @@ static Query* transformUpdateStmt(ParseState* pstate, UpdateStmt* stmt) assign_query_collations(pstate, qry); qry->hintState = stmt->hintState; + qry->hasIgnore = stmt->hasIgnore; return qry; } diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 6344e8e02..c353719df 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -18329,6 +18329,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re $6->returningList = $7; $6->withClause = $1; $6->hintState = create_hintstate($3); + $6->hasIgnore = ($6->hintState != NULL && $6->hintState->sql_ignore_hint && DB_IS_CMPT(B_FORMAT)); $$ = (Node *) $6; } | opt_with_clause INSERT hint_string INTO insert_target insert_rest upsert_clause returning_clause @@ -18383,6 +18384,8 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re $6->relation = $5; $6->returningList = $8; $6->withClause = $1; + $6->hintState = create_hintstate($3); + $6->hasIgnore = ($6->hintState != NULL && $6->hintState->sql_ignore_hint && DB_IS_CMPT(B_FORMAT)); #ifdef ENABLE_MULTIPLE_NODES if (t_thrd.proc->workingVersionNum >= UPSERT_ROW_STORE_VERSION_NUM) { UpsertClause *uc = makeNode(UpsertClause); @@ -18417,7 +18420,6 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re if ($7 != NULL) m->mergeWhenClauses = list_concat(list_make1($7), m->mergeWhenClauses); - m->hintState = create_hintstate($3); $$ = (Node *)m; } else { @@ -18426,6 +18428,7 @@ InsertStmt: opt_with_clause INSERT hint_string INTO insert_target insert_rest re $6->withClause = $1; $6->upsertClause = (UpsertClause *)$7; $6->hintState = create_hintstate($3); + $6->hasIgnore = ($6->hintState != NULL && $6->hintState->sql_ignore_hint && DB_IS_CMPT(B_FORMAT)); $$ = (Node *) $6; } } @@ -18670,6 +18673,7 @@ UpdateStmt: opt_with_clause UPDATE hint_string relation_expr_opt_alias n->returningList = $9; n->withClause = $1; n->hintState = create_hintstate($3); + n->hasIgnore = (n->hintState != NULL && n->hintState->sql_ignore_hint && DB_IS_CMPT(B_FORMAT)); $$ = (Node *)n; } ; diff --git a/src/common/backend/parser/hint_gram.y b/src/common/backend/parser/hint_gram.y index d23662c1d..90b943202 100755 --- a/src/common/backend/parser/hint_gram.y +++ b/src/common/backend/parser/hint_gram.y @@ -60,7 +60,7 @@ static double convert_to_numeric(Node *value); %token NestLoop_P MergeJoin_P HashJoin_P No_P Leading_P Rows_P Broadcast_P Redistribute_P BlockName_P TableScan_P IndexScan_P IndexOnlyScan_P Skew_P HINT_MULTI_NODE_P NULL_P TRUE_P FALSE_P Predpush_P - PredpushSameLevel_P Rewrite_P Gather_P Set_P USE_CPLAN_P USE_GPLAN_P ON_P OFF_P No_expand_P NO_GPC_P + PredpushSameLevel_P Rewrite_P Gather_P Set_P USE_CPLAN_P USE_GPLAN_P ON_P OFF_P No_expand_P SQL_IGNORE_P NO_GPC_P %nonassoc IDENT NULL_P @@ -163,6 +163,12 @@ join_hint_item: { $$ = $1; } + | SQL_IGNORE_P + { + SqlIgnoreHint *sql_ignore_hint = (SqlIgnoreHint *)makeNode(SqlIgnoreHint); + sql_ignore_hint->sql_ignore_hint = true; + $$ = (Node *) sql_ignore_hint; + } gather_hint: Gather_P '(' IDENT ')' diff --git a/src/common/backend/parser/hint_scan.l b/src/common/backend/parser/hint_scan.l index efe2e80fb..ba4d2935b 100755 --- a/src/common/backend/parser/hint_scan.l +++ b/src/common/backend/parser/hint_scan.l @@ -49,6 +49,7 @@ static const hintKeyword parsers[] = {HINT_GPLAN, USE_GPLAN_P}, {HINT_NO_EXPAND, No_expand_P}, {HINT_NO_GPC, NO_GPC_P}, + {HINT_SQL_IGNORE, SQL_IGNORE_P}, }; static const hintKeyword* HintKeywordLookup(const char *str); diff --git a/src/common/backend/parser/parse_hint.cpp b/src/common/backend/parser/parse_hint.cpp index 90794a82f..52643901e 100755 --- a/src/common/backend/parser/parse_hint.cpp +++ b/src/common/backend/parser/parse_hint.cpp @@ -185,8 +185,8 @@ static void append_value(StringInfo buf, Value* value, Node* node) } } -#define HINT_NUM 16 -#define HINT_KEYWORD_NUM 21 +#define HINT_NUM 17 +#define HINT_KEYWORD_NUM 22 typedef struct { HintKeyword keyword; @@ -214,6 +214,7 @@ const char* G_HINT_KEYWORD[HINT_KEYWORD_NUM] = { (char*) HINT_SET, (char*) HINT_CPLAN, (char*) HINT_GPLAN, + (char*) HINT_SQL_IGNORE, (char*) HINT_NO_GPC, }; @@ -1211,6 +1212,7 @@ HintState* HintStateCreate() hstate->set_hint = NIL; hstate->cache_plan_hint = NIL; hstate->no_expand_hint = NIL; + hstate->sql_ignore_hint = false; return hstate; } @@ -1386,6 +1388,11 @@ static void AddNoGPCHint(HintState* hstate, Hint* hint) } } +static void AddSqlIgnoreHint(HintState* hstate, Hint* hint) +{ + hstate->sql_ignore_hint = true; +} + typedef void (*AddHintFunc)(HintState*, Hint*); const AddHintFunc G_HINT_CREATOR[HINT_NUM] = { @@ -1404,6 +1411,7 @@ const AddHintFunc G_HINT_CREATOR[HINT_NUM] = { AddSetHint, AddPlanCacheHint, AddNoExpandHint, + AddSqlIgnoreHint, AddNoGPCHint, }; diff --git a/src/common/backend/utils/adt/float.cpp b/src/common/backend/utils/adt/float.cpp index 77a1c3a89..17f33b4cf 100644 --- a/src/common/backend/utils/adt/float.cpp +++ b/src/common/backend/utils/adt/float.cpp @@ -356,6 +356,17 @@ Datum float4in(PG_FUNCTION_ARGS) * if we get here, we have a legal double, still need to check to see if * it's a legal float4 */ + if (fcinfo->can_ignore) { + if (isinf((float4)val) && !isinf(val)) { + ereport(WARNING, (errmsg("value out of range: overflow"))); + PG_RETURN_FLOAT4(num < 0 ? FLT_MIN : FLT_MAX); + } + if (((float4)val) == 0.0 && val != 0) { + ereport(WARNING, (errmsg("value out of range: underflow"))); + PG_RETURN_FLOAT4(0); + } + PG_RETURN_FLOAT4((float4)val); + } CHECKFLOATVAL((float4)val, isinf(val), val == 0); PG_RETURN_FLOAT4((float4)val); @@ -1175,6 +1186,18 @@ Datum dtof(PG_FUNCTION_ARGS) { float8 num = PG_GETARG_FLOAT8(0); + if (fcinfo->can_ignore) { + if (isinf((float4)num) && !isinf(num)) { + ereport(WARNING, (errmsg("value out of range: overflow"))); + PG_RETURN_FLOAT4(num < 0 ? FLT_MIN : FLT_MAX); + } + if (((float4)num) == 0.0 && num != 0) { + ereport(WARNING, (errmsg("value out of range: underflow"))); + PG_RETURN_FLOAT4(0); + } + PG_RETURN_FLOAT4((float4)num); + } + CHECKFLOATVAL((float4)num, isinf(num), num == 0); PG_RETURN_FLOAT4((float4)num); @@ -1200,8 +1223,13 @@ Datum dtoi4(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT32_MAX * isn't, and might get rounded off, so avoid using it. */ - if (num < (float8)PG_INT32_MIN || num >= -((float8)PG_INT32_MIN) || isnan(num)) + if (num < (float8)PG_INT32_MIN || num >= -((float8)PG_INT32_MIN) || isnan(num)) { + if (fcinfo->can_ignore && !isnan(num)) { + ereport(WARNING, (errmsg("integer out of range"))); + PG_RETURN_INT32(num < (float8)PG_INT32_MIN ? INT_MIN : INT_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + } PG_RETURN_INT32((int32)num); } @@ -1226,8 +1254,13 @@ Datum dtoi2(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT16_MAX * isn't, and might get rounded off, so avoid using it. */ - if (num < (float8)PG_INT16_MIN || num >= -((float8)PG_INT16_MIN) || isnan(num)) + if (num < (float8)PG_INT16_MIN || num >= -((float8)PG_INT16_MIN) || isnan(num)) { + if (fcinfo->can_ignore && !isnan(num)) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT16(num < (float8)PG_INT16_MIN ? SHRT_MAX : SHRT_MIN); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); + } PG_RETURN_INT16((int16)num); } @@ -1272,6 +1305,17 @@ Datum ftoi4(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT32_MAX * isn't, and might get rounded off, so avoid using it. */ + + if (fcinfo->can_ignore && num < (float4)PG_INT32_MIN) { + ereport(WARNING, (errmsg("integer out of range"))); + PG_RETURN_INT32((int32)INT_MIN); + } + + if (fcinfo->can_ignore && num >= -((float4)PG_INT32_MIN)) { + ereport(WARNING, (errmsg("integer out of range"))); + PG_RETURN_INT32((int32)INT_MAX); + } + if (num < (float4)PG_INT32_MIN || num >= -((float4)PG_INT32_MIN) || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); @@ -1298,6 +1342,16 @@ Datum ftoi2(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT16_MAX * isn't, and might get rounded off, so avoid using it. */ + if (fcinfo->can_ignore && num < (float4)PG_INT16_MIN) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT16((int16)SHRT_MIN); + } + + if (fcinfo->can_ignore && num >= -((float4)PG_INT16_MIN)) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT16((int16)SHRT_MAX); + } + if (num < (float4)PG_INT16_MIN || num >= -((float4)PG_INT16_MIN) || isnan(num)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); diff --git a/src/common/backend/utils/adt/int.cpp b/src/common/backend/utils/adt/int.cpp index c39654b13..031d39c19 100644 --- a/src/common/backend/utils/adt/int.cpp +++ b/src/common/backend/utils/adt/int.cpp @@ -351,8 +351,13 @@ Datum i4toi2(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); - if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX)) + if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX)) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT16((int16)(arg1 < SHRT_MIN ? SHRT_MIN : SHRT_MAX)); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); + } PG_RETURN_INT16((int16)arg1); } @@ -1383,8 +1388,13 @@ Datum i2toi1(PG_FUNCTION_ARGS) { int16 arg1 = PG_GETARG_INT16(0); - if (arg1 < 0 || arg1 > UCHAR_MAX) + if (arg1 < 0 || arg1 > UCHAR_MAX) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8((uint8)(arg1 < 0 ? 0 : UCHAR_MAX)); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + } PG_RETURN_UINT8((uint8)arg1); } @@ -1400,8 +1410,13 @@ Datum i4toi1(PG_FUNCTION_ARGS) { int32 arg1 = PG_GETARG_INT32(0); - if (arg1 < 0 || arg1 > UCHAR_MAX) + if (arg1 < 0 || arg1 > UCHAR_MAX) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8((uint8)(arg1 < 0 ? 0 : UCHAR_MAX)); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + } PG_RETURN_UINT8((uint8)arg1); } @@ -1417,8 +1432,13 @@ Datum i8toi1(PG_FUNCTION_ARGS) { int64 arg1 = PG_GETARG_INT64(0); - if (arg1 < 0 || arg1 > UCHAR_MAX) + if (arg1 < 0 || arg1 > UCHAR_MAX) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8((uint8)(arg1 < 0 ? 0 : UCHAR_MAX)); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + } PG_RETURN_UINT8((uint8)arg1); } @@ -1441,8 +1461,13 @@ Datum f4toi1(PG_FUNCTION_ARGS) { float4 arg1 = PG_GETARG_FLOAT4(0); - if (arg1 < 0 || arg1 > UCHAR_MAX) + if (arg1 < 0 || arg1 > UCHAR_MAX) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8(arg1 < 0 ? 0 : UCHAR_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + } PG_RETURN_UINT8((uint8)arg1); } @@ -1451,8 +1476,13 @@ Datum f8toi1(PG_FUNCTION_ARGS) { float8 arg1 = PG_GETARG_FLOAT8(0); - if (arg1 < 0 || arg1 > UCHAR_MAX) + if (arg1 < 0 || arg1 > UCHAR_MAX) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8(arg1 < 0 ? 0 : UCHAR_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + } PG_RETURN_UINT8((uint8)arg1); } diff --git a/src/common/backend/utils/adt/int8.cpp b/src/common/backend/utils/adt/int8.cpp index 6dface912..d904a33dc 100644 --- a/src/common/backend/utils/adt/int8.cpp +++ b/src/common/backend/utils/adt/int8.cpp @@ -1092,8 +1092,13 @@ Datum int84(PG_FUNCTION_ARGS) result = (int32)arg; /* Test for overflow by reverse-conversion. */ - if ((int64)result != arg) + if ((int64)result != arg) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("integer out of range"))); + PG_RETURN_INT32(arg < INT_MIN ? INT_MIN : INT_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + } PG_RETURN_INT32(result); } @@ -1113,8 +1118,13 @@ Datum int82(PG_FUNCTION_ARGS) result = (int16)arg; /* Test for overflow by reverse-conversion. */ - if ((int64)result != arg) + if ((int64)result != arg) { + if (fcinfo->can_ignore) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT32(arg < SHRT_MIN ? SHRT_MIN : SHRT_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); + } PG_RETURN_INT16(result); } @@ -1149,8 +1159,13 @@ Datum dtoi8(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT64_MAX * isn't, and might get rounded off, so avoid using it. */ - if (num < (float8)PG_INT64_MIN || num >= -((float8)PG_INT64_MIN) || isnan(num)) + if (num < (float8)PG_INT64_MIN || num >= -((float8)PG_INT64_MIN) || isnan(num)) { + if (fcinfo->can_ignore && !isnan(num)) { + ereport(WARNING, (errmsg("bigint out of range"))); + PG_RETURN_INT64(num < (float8)PG_INT64_MIN ? LONG_MIN : LONG_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); + } PG_RETURN_INT64((int64)num); } @@ -1185,8 +1200,13 @@ Datum ftoi8(PG_FUNCTION_ARGS) * exact power of 2, so it will be represented exactly; but PG_INT64_MAX * isn't, and might get rounded off, so avoid using it. */ - if (num < (float4)PG_INT64_MIN || num >= -((float4)PG_INT64_MIN) || isnan(num)) + if (num < (float4)PG_INT64_MIN || num >= -((float4)PG_INT64_MIN) || isnan(num)) { + if (fcinfo->can_ignore && !isnan(num)) { + ereport(WARNING, (errmsg("bigint out of range"))); + PG_RETURN_INT64(num < (float4)PG_INT64_MIN ? LONG_MIN : LONG_MAX); + } ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); + } PG_RETURN_INT64((int64)num); } diff --git a/src/common/backend/utils/adt/numeric.cpp b/src/common/backend/utils/adt/numeric.cpp index e77a2e38a..e8cab3a80 100644 --- a/src/common/backend/utils/adt/numeric.cpp +++ b/src/common/backend/utils/adt/numeric.cpp @@ -166,7 +166,7 @@ static char* get_str_from_var_sci(NumericVar* var, int rscale); static void apply_typmod(NumericVar* var, int32 typmod); -static int32 numericvar_to_int32(const NumericVar* var); +static int32 numericvar_to_int32(const NumericVar* var, bool can_ignore = false); static double numeric_to_double_no_overflow(Numeric num); static double numericvar_to_double_no_overflow(NumericVar* var); @@ -2912,7 +2912,7 @@ Datum numeric_int4(PG_FUNCTION_ARGS) /* Convert to variable format, then convert to int4 */ init_var_from_num(num, &x); - result = numericvar_to_int32(&x); + result = numericvar_to_int32(&x, fcinfo->can_ignore); PG_RETURN_INT32(result); } @@ -2921,14 +2921,20 @@ Datum numeric_int4(PG_FUNCTION_ARGS) * exceeds the range of an int32, raise the appropriate error via * ereport(). The input NumericVar is *not* free'd. */ -static int32 numericvar_to_int32(const NumericVar* var) +static int32 numericvar_to_int32(const NumericVar* var, bool can_ignore) { int32 result; int64 val; - if (!numericvar_to_int64(var, &val)) + if (!numericvar_to_int64(var, &val, can_ignore)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); + /* return INT32_MAX/INT32_MIN if SQL can ignore overflowing */ + if (can_ignore && (val > INT_MAX || val < INT_MIN)) { + ereport(WARNING, (errmsg("integer out of range"))); + return val > INT_MAX ? INT_MAX : INT_MIN; + } + /* Down-convert to int4 */ result = (int32)val; @@ -2975,7 +2981,7 @@ Datum numeric_int8(PG_FUNCTION_ARGS) /* Convert to variable format and thence to int8 */ init_var_from_num(num, &x); - if (!numericvar_to_int64(&x, &result)) + if (!numericvar_to_int64(&x, &result, fcinfo->can_ignore)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); PG_RETURN_INT64(result); @@ -3018,9 +3024,15 @@ Datum numeric_int2(PG_FUNCTION_ARGS) /* Convert to variable format and thence to int8 */ init_var_from_num(num, &x); - if (!numericvar_to_int64(&x, &val)) + if (!numericvar_to_int64(&x, &val, fcinfo->can_ignore)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("smallint out of range"))); + /* return INT16_MAX/INT16_MIN if SQL can ignore overflowing */ + if (fcinfo->can_ignore && (val > SHRT_MAX || val < SHRT_MIN)) { + ereport(WARNING, (errmsg("smallint out of range"))); + PG_RETURN_INT16(val > SHRT_MAX ? SHRT_MAX : SHRT_MIN); + } + /* Down-convert to int2 */ result = (int16)val; @@ -3069,13 +3081,19 @@ Datum numeric_int1(PG_FUNCTION_ARGS) /* Convert to variable format and thence to uint8 */ init_var_from_num(num, &x); - if (x.sign == NUMERIC_NEG) { + if (x.sign == NUMERIC_NEG && !fcinfo->can_ignore) { ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); } - if (!numericvar_to_int64(&x, &val)) + if (!numericvar_to_int64(&x, &val, fcinfo->can_ignore)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("tinyint out of range"))); + /* return UINT8_MAX/UINT8_MIN if SQL can ignore overflowing */ + if (fcinfo->can_ignore && (val > UCHAR_MAX || val < 0)) { + ereport(WARNING, (errmsg("tinyint out of range"))); + PG_RETURN_UINT8(val > UCHAR_MAX ? UCHAR_MAX : 0); + } + /* Down-convert to int1 */ result = (uint8)val; @@ -3211,7 +3229,11 @@ Datum numeric_float4(PG_FUNCTION_ARGS) tmp = DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(num))); - result = DirectFunctionCall1(float4in, CStringGetDatum(tmp)); + if (fcinfo->can_ignore) { + result = DirectFunctionCall1Coll(float4in, InvalidOid, CStringGetDatum(tmp), true); + } else { + result = DirectFunctionCall1(float4in, CStringGetDatum(tmp)); + } pfree_ext(tmp); @@ -4594,9 +4616,13 @@ static void apply_typmod(NumericVar* var, int32 typmod) /* * Convert numeric to int8, rounding if needed. * + * Note: param can_ignore controls the function raising ERROR or WARNING. TRUE means overflowing will report WARNING + * and set result to INT64_MAX/INT64_MIN instead. FALSE make it raise ERROR directly. FALSE DEFAULTED. It should be only + * used for controls of keyword IGNORE. + * * If overflow, return false (no error is raised). Return true if okay. */ -bool numericvar_to_int64(const NumericVar* var, int64* result) +bool numericvar_to_int64(const NumericVar* var, int64* result, bool can_ignore) { NumericDigit* digits = NULL; int ndigits; @@ -4638,12 +4664,22 @@ bool numericvar_to_int64(const NumericVar* var, int64* result) for (i = 1; i <= weight; i++) { if (unlikely(pg_mul_s64_overflow(val, NBASE, &val))) { free_var(&rounded); + if (can_ignore) { + *result = neg ? LONG_MIN : LONG_MAX; + ereport(WARNING, (errmsg("value out of range"))); + return true; + } return false; } if (i < ndigits) { if (unlikely(pg_sub_s64_overflow(val, digits[i], &val))) { free_var(&rounded); + if (can_ignore) { + *result = neg ? LONG_MIN : LONG_MAX; + ereport(WARNING, (errmsg("value out of range"))); + return true; + } return false; } } diff --git a/src/common/backend/utils/adt/varchar.cpp b/src/common/backend/utils/adt/varchar.cpp index e0a187811..25126ab85 100644 --- a/src/common/backend/utils/adt/varchar.cpp +++ b/src/common/backend/utils/adt/varchar.cpp @@ -301,10 +301,12 @@ Datum bpchar(PG_FUNCTION_ARGS) if (!isExplicit) { for (i = maxmblen; i < len; i++) - if (s[i] != ' ') - ereport(ERROR, + if (s[i] != ' ') { + ereport(fcinfo->can_ignore ? WARNING : ERROR, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), - errmsg("value too long for type character(%d)", maxlen))); + errmsg("value too long for type character(%d)", maxlen))); + break; + } } len = maxmblen; @@ -605,10 +607,12 @@ Datum varchar(PG_FUNCTION_ARGS) if (!isExplicit) { for (i = maxmblen; i < len; i++) - if (s_data[i] != ' ') - ereport(ERROR, + if (s_data[i] != ' ') { + ereport(fcinfo->can_ignore ? WARNING : ERROR, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("value too long for type character varying(%d)", maxlen))); + break; + } } PG_RETURN_VARCHAR_P((VarChar*)cstring_to_text_with_len(s_data, maxmblen)); @@ -1221,10 +1225,12 @@ Datum nvarchar2(PG_FUNCTION_ARGS) if (!isExplicit) { for (i = maxmblen; i < len; i++) - if (s_data[i] != ' ') - ereport(ERROR, + if (s_data[i] != ' ') { + ereport(fcinfo->can_ignore ? WARNING: ERROR, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("value too long for type nvarchar2(%d)", maxlen))); + break; + } } PG_RETURN_NVARCHAR2_P((NVarChar2*)cstring_to_text_with_len(s_data, maxmblen)); diff --git a/src/common/backend/utils/fmgr/fmgr.cpp b/src/common/backend/utils/fmgr/fmgr.cpp index 7e1ca35cc..a32b63477 100755 --- a/src/common/backend/utils/fmgr/fmgr.cpp +++ b/src/common/backend/utils/fmgr/fmgr.cpp @@ -1220,7 +1220,7 @@ static Datum fmgr_security_definer(PG_FUNCTION_ARGS) * are allowed to be NULL. Also, the function cannot be one that needs to * look at FmgrInfo, since there won't be any. */ -Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) +Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1, bool can_ignore) { FunctionCallInfoData fcinfo; Datum result; @@ -1229,6 +1229,7 @@ Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) fcinfo.arg[0] = arg1; fcinfo.argnull[0] = false; + fcinfo.can_ignore = can_ignore; result = (*func)(&fcinfo); diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index 9612e92ae..a5f733049 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -59,7 +59,7 @@ bool open_join_children = true; bool will_shutdown = false; /* hard-wired binary version number */ -const uint32 GRAND_VERSION_NUM = 92608; +const uint32 GRAND_VERSION_NUM = 92609; const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522; const uint32 UPSERT_WHERE_VERSION_NUM = 92514; @@ -103,6 +103,7 @@ const uint32 SCAN_BATCH_MODE_VERSION_NUM = 92568; const uint32 PUBLICATION_VERSION_NUM = 92580; const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92606; const uint32 PUBLICATION_INITIAL_DATA_VERSION_NAME = 92607; +const uint32 KEYWORD_IGNORE_COMPART_VERSION_NUM = 92609; /* Version number of the guc parameter backend_version added in V500R001C20 */ const uint32 V5R1C20_BACKEND_VERSION_NUM = 92305; diff --git a/src/common/backend/utils/misc/guc/guc_sql.cpp b/src/common/backend/utils/misc/guc/guc_sql.cpp index 9139bb39d..92769b41d 100755 --- a/src/common/backend/utils/misc/guc/guc_sql.cpp +++ b/src/common/backend/utils/misc/guc/guc_sql.cpp @@ -165,6 +165,8 @@ static void assign_convert_string_to_digit(bool newval, void* extra); static void AssignUStoreAttr(const char* newval, void* extra); static bool check_snapshot_delimiter(char** newval, void** extra, GucSource source); static bool check_snapshot_separator(char** newval, void** extra, GucSource source); +static bool check_sql_ignore_strategy(char** newval, void** extra, GucSource source); +static void assign_sql_ignore_strategy(const char* newval, void* extra); static void InitSqlConfigureNamesBool(); @@ -332,6 +334,13 @@ static const struct behavior_compat_entry behavior_compat_options[OPT_MAX] = { {"char_coerce_compat", OPT_CHAR_COERCE_COMPAT} }; +// increase SQL_IGNORE_STRATEGY_NUM if we need more strategy +#define SQL_IGNORE_STRATEGY_NUM 2 +static const struct config_enum_entry sql_ignore_strategy[] = { + {"ignore_null", SQL_IGNORE_NULL, false}, + {"overwrite_null", SQL_OVERWRITE_NULL, false}, +}; + /* * Contents of GUC tables * @@ -2686,6 +2695,18 @@ static void InitSqlConfigureNamesString() check_snapshot_delimiter, NULL, NULL}, + {{"sql_ignore_strategy", + PGC_USERSET, + NODE_ALL, + COMPAT_OPTIONS, + gettext_noop("Handling strategy when SQL has keyword IGNORE and gets ERROR."), + NULL, + }, + &u_sess->attr.attr_sql.sql_ignore_strategy_string, + "ignore_null", + check_sql_ignore_strategy, + assign_sql_ignore_strategy, + NULL}, {{NULL, (GucContext)0, (GucNodeType)0, @@ -3361,3 +3382,27 @@ static bool check_snapshot_separator(char** newval, void** extra, GucSource sour return (strlen(*newval) == 1 && (!u_sess->attr.attr_sql.db4ai_snapshot_version_delimiter || **newval != *u_sess->attr.attr_sql.db4ai_snapshot_version_delimiter)); } + +static bool check_sql_ignore_strategy(char** newval, void** extra, GucSource source) +{ + if (NULL == newval) { + return false; + } + for (int start = 0; start < SQL_IGNORE_STRATEGY_NUM; start++) { + if (strcmp((const char*)*newval, sql_ignore_strategy[start].name) == 0) { + return true; + } + } + GUC_check_errdetail("invalid value for sql ignore strategy."); + return false; +} + +static void assign_sql_ignore_strategy(const char* newval, void* extra) { + for (int start = 0; start < SQL_IGNORE_STRATEGY_NUM; start++) { + if (strcmp((const char*)newval, sql_ignore_strategy[start].name) == 0) { + u_sess->utils_cxt.sql_ignore_strategy_val = sql_ignore_strategy[start].val; + return; + } + } + u_sess->utils_cxt.sql_ignore_strategy_val = sql_ignore_strategy[0].val; +} \ No newline at end of file diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index 59b701227..1a86b2d47 100755 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -890,6 +890,7 @@ PlannedStmt* standard_planner(Query* parse, int cursorOptions, ParamListInfo bou result->invalItems = glob->invalItems; result->nParamExec = glob->nParamExec; result->noanalyze_rellist = (List*)copyObject(t_thrd.postgres_cxt.g_NoAnalyzeRelNameList); + result->hasIgnore = parse->hasIgnore; if (IS_PGXC_COORDINATOR && (t_thrd.proc->workingVersionNum < 92097 || total_num_streams > 0)) { diff --git a/src/gausskernel/optimizer/prep/prepjointree.cpp b/src/gausskernel/optimizer/prep/prepjointree.cpp index 2187138e8..2e1fae2f1 100755 --- a/src/gausskernel/optimizer/prep/prepjointree.cpp +++ b/src/gausskernel/optimizer/prep/prepjointree.cpp @@ -1025,6 +1025,7 @@ void pull_up_subquery_hint(PlannerInfo* root, Query* parse, HintState* hint_stat parse->hintState->skew_hint = list_concat(parse->hintState->skew_hint, hint_state->skew_hint); parse->hintState->nall_hints = parse->hintState->nall_hints + hint_state->nall_hints; parse->hintState->multi_node_hint = hint_state->multi_node_hint; + parse->hintState->sql_ignore_hint = hint_state->sql_ignore_hint; /* no_expand hint, set hint, no_gpc hint should not be pulled up */ if (hint_state->block_name_hint) { diff --git a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp index c5cabcf01..3a8c3b831 100644 --- a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp +++ b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp @@ -3156,6 +3156,10 @@ List *QueryRewriteRefresh(Query *parse_tree) if (hintState != NULL && hintState->multi_node_hint) { appendStringInfo(cquery, " /*+ multinode */ "); } + + if (hintState != NULL && hintState->sql_ignore_hint) { + appendStringInfo(cquery, " /*+ ignore_error */ "); + } if (relation->schemaname) { appendStringInfo(cquery, " INTO %s.%s", quote_identifier(relation->schemaname), diff --git a/src/gausskernel/optimizer/util/clauses.cpp b/src/gausskernel/optimizer/util/clauses.cpp index a9a155d74..8261e1607 100644 --- a/src/gausskernel/optimizer/util/clauses.cpp +++ b/src/gausskernel/optimizer/util/clauses.cpp @@ -4171,7 +4171,11 @@ static Expr* evaluate_function(Oid funcid, Oid result_type, int32 result_typmod, newexpr->args = args; newexpr->location = -1; - return evaluate_expr((Expr*)newexpr, result_type, result_typmod, result_collid); + bool can_ignore = false; + if (context != NULL && context->root != NULL && context->root->parse != NULL && context->root->parse->hasIgnore) { + can_ignore = true; + } + return evaluate_expr((Expr*)newexpr, result_type, result_typmod, result_collid, can_ignore); } /* @@ -4600,8 +4604,10 @@ static void sql_inline_error_callback(void* arg) * * We use the executor's routine ExecEvalExpr() to avoid duplication of * code and ensure we get the same result as the executor would get. + * + * Note: parameter can_ignore indicates whether ERROR is ignorable when casting type. TRUE if SQL has keyword IGNORE. */ -Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result_collation) +Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result_collation, bool can_ignore) { EState* estate = NULL; ExprState* exprstate = NULL; @@ -4636,7 +4642,11 @@ Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result * fortuitous, but it's not so unreasonable --- a constant expression does * not depend on context, by definition, n'est ce pas? */ - const_val = ExecEvalExprSwitchContext(exprstate, GetPerTupleExprContext(estate), &const_is_null, NULL); + ExprContext* econtext = GetPerTupleExprContext(estate); + if (econtext != NULL) { + econtext->can_ignore = can_ignore; + } + const_val = ExecEvalExprSwitchContext(exprstate, econtext, &const_is_null, NULL); /* Get info needed about result datatype */ get_typlenbyval(result_type, &resultTypLen, &resultTypByVal); diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 6c3225a37..bcc847a9e 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -465,6 +465,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt) utils_cxt->memory_context_limited_white_list = NULL; utils_cxt->enable_memory_context_control = false; + utils_cxt->sql_ignore_strategy_val = 0; (void)syscalllockInit(&utils_cxt->deleMemContextMutex); } diff --git a/src/gausskernel/runtime/executor/execMain.cpp b/src/gausskernel/runtime/executor/execMain.cpp index cf58f8fdd..cc15fe0d4 100755 --- a/src/gausskernel/runtime/executor/execMain.cpp +++ b/src/gausskernel/runtime/executor/execMain.cpp @@ -2449,7 +2449,7 @@ static const char *ExecRelCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *sl return NULL; } -void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate) +bool ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate) { Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); @@ -2481,21 +2481,23 @@ void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState ExecBuildSlotValueDescription(RelationGetRelid(rel), slot, tupdesc, modifiedCols, maxfieldlen); } - ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), + bool can_ignore = estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore; + ereport(can_ignore ? WARNING : ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" violates not-null constraint", NameStr(tupdesc->attrs[attrChk - 1]->attname)), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0)); + return false; } } } if (constr->num_check == 0) { - return; + return true; } const char *failed = ExecRelCheck(resultRelInfo, slot, estate); if (failed == NULL) { - return; + return true; } char *val_desc = NULL; @@ -2525,6 +2527,7 @@ void ExecConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState errcause("some rows copy failed"), erraction("set client_min_messages = info for more details"))); } + return true; } /* diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index e6f1004b6..bd3f7a66b 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -2389,6 +2389,10 @@ static Datum ExecMakeFunctionResultNoSets( fcinfo->context = (Node *)node; } + if (econtext) { + fcinfo->can_ignore = econtext->can_ignore; + } + /* * Incause of connet_by_root() and sys_connect_by_path() we need get the * current scan tuple slot so attach the econtext here diff --git a/src/gausskernel/runtime/executor/execScan.cpp b/src/gausskernel/runtime/executor/execScan.cpp index fefade4a2..b1bfd81fc 100644 --- a/src/gausskernel/runtime/executor/execScan.cpp +++ b/src/gausskernel/runtime/executor/execScan.cpp @@ -196,6 +196,9 @@ TupleTableSlot* ExecScan(ScanState* node, ExecScanAccessMtd access_mtd, /* funct * Found a satisfactory scan tuple. */ if (proj_info != NULL) { + if (node->ps.state && node->ps.state->es_plannedstmt) { + econtext->can_ignore = node->ps.state->es_plannedstmt->hasIgnore; + } /* * Form a projection tuple, store it in the result tuple slot * and return it --- unless we find we can project no tuples diff --git a/src/gausskernel/runtime/executor/execUtils.cpp b/src/gausskernel/runtime/executor/execUtils.cpp index 84fd23666..58e0be071 100644 --- a/src/gausskernel/runtime/executor/execUtils.cpp +++ b/src/gausskernel/runtime/executor/execUtils.cpp @@ -63,6 +63,13 @@ #include "optimizer/var.h" #include "utils/resowner.h" #include "miscadmin.h" +#include "utils/date.h" +#include "utils/nabstime.h" +#include "utils/geo_decls.h" +#include "utils/varbit.h" +#include "utils/json.h" +#include "utils/jsonb.h" +#include "utils/xml.h" static bool get_last_attnums(Node* node, ProjectionInfo* projInfo); static bool index_recheck_constraint( @@ -1831,7 +1838,6 @@ List* ExecInsertIndexTuples(TupleTableSlot* slot, ItemPointer tupleid, EState* e } else { checkUnique = UNIQUE_CHECK_PARTIAL; } - satisfiesConstraint = index_insert(actualindex, /* index relation */ values, /* array of index Datums */ isnull, /* null flags */ @@ -2429,4 +2435,172 @@ void PthreadRwLockInit(pthread_rwlock_t* rwlock, pthread_rwlockattr_t *attr) ereport(ERROR, (errcode(ERRCODE_INITIALIZE_FAILED), errmsg("init rwlock failed"))); } +} + +/* + * Get defaulted value of specific time type + */ +static Datum GetTimeTypeZeroValue(Form_pg_attribute att_tup) +{ + Datum result; + switch (att_tup->atttypid) { + case TIMESTAMPOID: { + result = (Datum)DirectFunctionCall3(timestamp_in, CStringGetDatum("now"), ObjectIdGetDatum(InvalidOid), + Int32GetDatum(-1)); + break; + } + case TIMESTAMPTZOID: { + result = clock_timestamp(NULL); + break; + } + case TIMETZOID: { + result = (Datum)DirectFunctionCall3( + timetz_in, CStringGetDatum("00:00:00"), ObjectIdGetDatum(0), Int32GetDatum(-1)); + break; + } + case INTERVALOID: { + result = (Datum)DirectFunctionCall3( + interval_in, CStringGetDatum("00:00:00"), ObjectIdGetDatum(0), Int32GetDatum(-1)); + break; + } + case TINTERVALOID: { + Datum epoch = (Datum)DirectFunctionCall1(timestamp_abstime, (TimestampGetDatum(SetEpochTimestamp()))); + result = (Datum)DirectFunctionCall2(mktinterval, epoch, epoch); + break; + } + case SMALLDATETIMEOID: { + result = (Datum)DirectFunctionCall3( + smalldatetime_in, CStringGetDatum("1970-01-01 08:00:00"), ObjectIdGetDatum(0), Int32GetDatum(-1)); + break; + } + default: { + 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)); + break; + } + case NAMEOID: { + result = (Datum)DirectFunctionCall1(namein, CStringGetDatum("")); + break; + } + case POINTOID: { + result = (Datum)DirectFunctionCall1(point_in, CStringGetDatum("(0,0)")); + break; + } + case PATHOID: { + result = (Datum)DirectFunctionCall1(path_in, CStringGetDatum("0,0")); + break; + } + case POLYGONOID: { + result = (Datum)DirectFunctionCall1(poly_in, CStringGetDatum("(0,0)")); + break; + } + case CIRCLEOID: { + result = (Datum)DirectFunctionCall1(circle_in, CStringGetDatum("0,0,0")); + break; + } + case LSEGOID: + case BOXOID: { + result = (Datum)DirectFunctionCall1(box_in, CStringGetDatum("0,0,0,0")); + break; + } + case JSONOID: { + result = (Datum)DirectFunctionCall1(json_in, CStringGetDatum("0")); + break; + } + case JSONBOID: { + result = (Datum)DirectFunctionCall1(jsonb_in, CStringGetDatum("0")); + break; + } + case XMLOID: { + result = (Datum)DirectFunctionCall1(xml_in, CStringGetDatum("")); + (Datum)DirectFunctionCall1(numeric_in, CStringGetDatum("0")); + break; + } + case BITOID: { + result = (Datum)DirectFunctionCall3(bit_in, CStringGetDatum(""), ObjectIdGetDatum(0), Int32GetDatum(-1)); + break; + } + case NUMERICOID: { + result = + (Datum)DirectFunctionCall3(numeric_in, CStringGetDatum("0"), ObjectIdGetDatum(0), Int32GetDatum(0)); + break; + } + default: { + bool typeIsVarlena = (!att_tup->attbyval) && (att_tup->attlen == -1); + if (typeIsVarlena) { + result = CStringGetTextDatum(""); + } else { + result = (Datum)0; + } + break; + } + } + return result; +} + +/* + * Replace tuple from the slot with a new one. The new tuple will replace null column with defaulted values according to + * its type. + */ +Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot *slot) +{ + /* find out all null column first */ + int natts = tupleDesc->natts; + Datum values[natts]; + bool replaces[natts]; + bool nulls[natts]; + errno_t rc; + + rc = memset_s(values, sizeof(values), 0, sizeof(values)); + securec_check(rc, "\0", "\0"); + rc = memset_s(nulls, sizeof(nulls), false, sizeof(nulls)); + securec_check(rc, "\0", "\0"); + rc = memset_s(replaces, sizeof(replaces), false, sizeof(replaces)); + securec_check(rc, "\0", "\0"); + + 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]); + replaces[attrChk - 1] = true; + } + } + Tuple oldTup = slot->tts_tuple; + Tuple newTup = tableam_tops_modify_tuple(oldTup, tupleDesc, values, nulls, replaces); + + /* revise members of slot */ + slot->tts_tuple = newTup; + for (attrChk = 1; attrChk <= natts; attrChk++) { + if (!replaces[attrChk - 1]) { + continue; + } + slot->tts_isnull[attrChk - 1] = false; + slot->tts_values[attrChk - 1] = values[attrChk - 1]; + } + + tableam_tops_free_tuple(oldTup); + return newTup; } \ No newline at end of file diff --git a/src/gausskernel/runtime/executor/nodeModifyTable.cpp b/src/gausskernel/runtime/executor/nodeModifyTable.cpp index 31817a46b..c16e057da 100644 --- a/src/gausskernel/runtime/executor/nodeModifyTable.cpp +++ b/src/gausskernel/runtime/executor/nodeModifyTable.cpp @@ -903,10 +903,16 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple #ifdef ENABLE_MOT if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { - if (state->mt_insert_constr_slot == NULL) { - ExecConstraints(result_rel_info, slot, estate); - } else { - ExecConstraints(result_rel_info, state->mt_insert_constr_slot, estate); + TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; + if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { + tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, tmp_slot, estate); + } else { + return NULL; + } } } } @@ -941,10 +947,17 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple bucket_id = computeTupleBucketId(result_relation_desc, (HeapTuple)tuple); } if (result_relation_desc->rd_att->constr) { - if (state->mt_insert_constr_slot == NULL) - ExecConstraints(result_rel_info, slot, estate); - else - ExecConstraints(result_rel_info, state->mt_insert_constr_slot, estate); + TupleTableSlot *tmp_slot = state->mt_insert_constr_slot == NULL ? slot : state->mt_insert_constr_slot; + if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { + tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, tmp_slot, estate); + } else { + return NULL; + } + } } #ifdef PGXC @@ -1058,6 +1071,11 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple */ new_id = InvalidOid; RangeTblEntry *rte = exec_rt_fetch(result_rel_info->ri_RangeTableIndex, estate); + bool isgpi = false; + ConflictInfoData conflictInfo; + Oid conflictPartOid = InvalidOid; + int2 conflictBucketid = InvalidBktId; + switch (result_relation_desc->rd_rel->parttype) { case PARTTYPE_NON_PARTITIONED_RELATION: case PARTTYPE_VALUE_PARTITIONED_RELATION: { @@ -1079,6 +1097,16 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple searchHBucketFakeRelation(estate->esfRelations, estate->es_query_cxt, result_relation_desc, bucket_id, target_rel); } + // check unique constraints first if SQL has keyword IGNORE + if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, target_rel, partition, &isgpi, + bucket_id, &conflictInfo, &conflictPartOid, + &conflictBucketid)) { + ereport(WARNING, + (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(target_rel)))); + return NULL; + } new_id = tableam_tuple_insert(target_rel, tuple, estate->es_output_cid, 0, NULL); if (rel_isblockchain) { @@ -1091,7 +1119,12 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple case PARTTYPE_PARTITIONED_RELATION: { /* get partititon oid for insert the record */ - partition_id = heapTupleGetPartitionId(result_relation_desc, tuple); + partition_id = + heapTupleGetPartitionId(result_relation_desc, tuple, false, estate->es_plannedstmt->hasIgnore); + /* if cannot find valid partition oid and sql has keyword ignore, return and don't insert */ + if (estate->es_plannedstmt->hasIgnore && partition_id == InvalidOid) { + return NULL; + } CheckPartitionOidForSpecifiedPartition(rte, partition_id); searchFakeReationForPartitionOid(estate->esfRelations, estate->es_query_cxt, @@ -1106,6 +1139,15 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple #endif /* ENABLE_MULTIPLE_NODES */ } else { target_rel = heap_rel; + /* check unique constraints first if SQL has keyword IGNORE */ + if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, target_rel, partition, &isgpi, bucket_id, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, + (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(target_rel)))); + return NULL; + } tableam_tops_update_tuple_with_oid(heap_rel, tuple, slot); if (bucket_id != InvalidBktId) { searchHBucketFakeRelation( @@ -1128,7 +1170,11 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple Partition subPart = NULL; /* get partititon oid for insert the record */ - partitionId = heapTupleGetPartitionId(result_relation_desc, tuple); + partitionId = heapTupleGetPartitionId(result_relation_desc, tuple, false, + estate->es_plannedstmt->hasIgnore); + if (estate->es_plannedstmt->hasIgnore && partitionId == InvalidOid) { + return NULL; + } CheckPartitionOidForSpecifiedPartition(rte, partitionId); searchFakeReationForPartitionOid(estate->esfRelations, estate->es_query_cxt, @@ -1136,7 +1182,10 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple RowExclusiveLock); /* get subpartititon oid for insert the record */ - subPartitionId = heapTupleGetPartitionId(partRel, tuple); + subPartitionId = heapTupleGetPartitionId(partRel, tuple, false, estate->es_plannedstmt->hasIgnore); + if (estate->es_plannedstmt->hasIgnore && subPartitionId == InvalidOid) { + return NULL; + } CheckSubpartitionOidForSpecifiedSubpartition(rte, partitionId, subPartitionId); searchFakeReationForPartitionOid(estate->esfRelations, estate->es_query_cxt, partRel, @@ -1147,6 +1196,15 @@ TupleTableSlot* ExecInsertT(ModifyTableState* state, TupleTableSlot* slot, Tuple partition = subPart; target_rel = heap_rel; + // check unique constraints first if SQL has keyword IGNORE + if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, target_rel, partition, &isgpi, bucket_id, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, + (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(result_relation_desc)))); + return NULL; + } tableam_tops_update_tuple_with_oid(heap_rel, tuple, slot); if (bucket_id != InvalidBktId) { searchHBucketFakeRelation(estate->esfRelations, estate->es_query_cxt, heap_rel, bucket_id, @@ -1669,6 +1727,13 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, uint64 res_hash; uint64 hash_del = 0; bool is_record = false; + /* + * flag to tell whether violate unique constraint for update indices + */ + bool isgpi = false; + ConflictInfoData conflictInfo; + Oid conflictPartOid = InvalidOid; + int2 conflictBucketid = InvalidBktId; #ifdef PGXC RemoteQueryState* result_remote_rel = NULL; #endif @@ -1729,7 +1794,7 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, #endif result_rel_info->ri_TrigDesc && result_rel_info->ri_TrigDesc->trig_update_before_row) { #ifdef PGXC - slot = ExecBRUpdateTriggers(estate, epqstate, result_rel_info, oldPartitionOid, + slot = ExecBRUpdateTriggers(estate, epqstate, result_rel_info, oldPartitionOid, bucketid, oldtuple, tupleid, slot); #else slot = ExecBRUpdateTriggers(estate, epqstate, result_rel_info, tupleid, slot); @@ -1786,10 +1851,16 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, #ifdef ENABLE_MOT if (result_rel_info->ri_FdwRoutine->GetFdwType && result_rel_info->ri_FdwRoutine->GetFdwType() == MOT_ORC) { if (result_relation_desc->rd_att->constr) { - if (node->mt_insert_constr_slot == NULL) { - ExecConstraints(result_rel_info, slot, estate); - } else { - ExecConstraints(result_rel_info, node->mt_insert_constr_slot, estate); + TupleTableSlot *tmp_slot = node->mt_insert_constr_slot == NULL ? slot : node->mt_insert_constr_slot; + if (!ExecConstraints(result_rel_info, slot, estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { + tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), slot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, slot, estate); + } else { + return NULL; + } } } } @@ -1827,10 +1898,17 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, Assert(RELATION_HAS_BUCKET(result_relation_desc) == (bucketid != InvalidBktId)); lreplace: if (result_relation_desc->rd_att->constr) { - if (node->mt_update_constr_slot == NULL) - ExecConstraints(result_rel_info, slot, estate); - else - ExecConstraints(result_rel_info, node->mt_update_constr_slot, estate); + TupleTableSlot *tmp_slot = node->mt_update_constr_slot == NULL ? slot : node->mt_update_constr_slot; + if (!ExecConstraints(result_rel_info, tmp_slot, estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val == SQL_OVERWRITE_NULL) { + tuple = ReplaceTupleNullCol(RelationGetDescr(result_relation_desc), tmp_slot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, tmp_slot, estate); + } else { + return NULL; + } + } } #ifdef PGXC @@ -1859,6 +1937,21 @@ lreplace: parent_relation = result_relation_desc; } + /* + * check constraints first if SQL has keyword IGNORE + * + * Note: we need to exclude the case of UPSERT_UPDATE, so that upsert could be successfully finished. + */ + if (node->mt_upsert->us_action != UPSERT_UPDATE && estate->es_plannedstmt && + estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, result_relation_desc, partition, &isgpi, bucketid, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, + (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(result_relation_desc)))); + return NULL; + } + /* * If target relation is under blockchain schema, * we should get the target tuple hash before updating. @@ -2017,8 +2110,9 @@ lreplace: exec_index_tuples_state.targetPartRel = NULL; exec_index_tuples_state.p = NULL; exec_index_tuples_state.conflict = NULL; - recheck_indexes = tableam_tops_exec_update_index_tuples(slot, oldslot, fake_relation, - node, tuple, tupleid, exec_index_tuples_state, bucketid, modifiedIdxAttrs); + recheck_indexes = tableam_tops_exec_update_index_tuples( + slot, oldslot, fake_relation, node, tuple, tupleid, exec_index_tuples_state, bucketid, + modifiedIdxAttrs); } if (oldslot) { @@ -2046,7 +2140,8 @@ lreplace: if (u_sess->exec_cxt.route->fileExist) { new_partId = u_sess->exec_cxt.route->partitionId; } else { - ereport(ERROR, (errmodule(MOD_EXECUTOR), + int level = estate->es_plannedstmt->hasIgnore ? WARNING : ERROR; + ereport(level, (errmodule(MOD_EXECUTOR), (errcode(ERRCODE_PARTITION_ERROR), errmsg("fail to update partitioned table \"%s\"", RelationGetRelationName(result_relation_desc)), @@ -2055,6 +2150,9 @@ lreplace: releaseDummyRelation(&partRel); partitionClose(result_relation_desc, part, NoLock); + if (!u_sess->exec_cxt.route->fileExist && estate->es_plannedstmt->hasIgnore) { + return NULL; + } } if (oldPartitionOid == new_partId) { @@ -2076,6 +2174,12 @@ lreplace: * it can not be a range area */ if (u_sess->exec_cxt.route->partArea != PART_AREA_INTERVAL) { + if (epqstate->parentestate->es_plannedstmt->hasIgnore) { + ereport(WARNING, (errmsg("fail to update partitioned table \"%s\".new tuple does not " + "map to any table partition.", + RelationGetRelationName(result_relation_desc)))); + return NULL; + } ereport(ERROR, (errmodule(MOD_EXECUTOR), (errcode(ERRCODE_PARTITION_ERROR), @@ -2128,6 +2232,17 @@ lreplace: estate->esfRelations, estate->es_query_cxt, fake_relation, bucketid, fake_relation); } + /* + * check constraints first if SQL has keyword IGNORE + */ + if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, fake_relation, partition, &isgpi, bucketid, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(result_relation_desc)))); + return NULL; + } + if (result_relation_desc->rd_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); hash_del = get_user_tupleid_hash(fake_relation, tupleid); @@ -2275,8 +2390,9 @@ lreplace: exec_index_tuples_state.targetPartRel = fake_part_rel; exec_index_tuples_state.p = partition; exec_index_tuples_state.conflict = NULL; - recheck_indexes = tableam_tops_exec_update_index_tuples(slot, oldslot, fake_relation, - node, tuple, tupleid, exec_index_tuples_state, bucketid, modifiedIdxAttrs); + recheck_indexes = tableam_tops_exec_update_index_tuples( + slot, oldslot, fake_relation, node, tuple, tupleid, exec_index_tuples_state, bucketid, + modifiedIdxAttrs); } if (oldslot) { @@ -2286,26 +2402,61 @@ lreplace: /* partition table, row movement */ /* partition table, row movement, heap */ + /* init old_partition vars and new inserted partition vars first */ + Partition old_partition = NULL; + Relation old_fake_relation = NULL; + TupleTableSlot* oldslot = NULL; + uint64 hash_del = 0; + + searchFakeReationForPartitionOid(estate->esfRelations, + estate->es_query_cxt, + result_relation_desc, + oldPartitionOid, + old_fake_relation, + old_partition, + RowExclusiveLock); + + if (bucketid != InvalidBktId) { + searchHBucketFakeRelation( + estate->esfRelations, estate->es_query_cxt, old_fake_relation, bucketid, old_fake_relation); + } + + Partition insert_partition = NULL; + Relation fake_insert_relation = NULL; + + if (need_create_file) { + new_partId = AddNewIntervalPartition(result_relation_desc, tuple); + } + + searchFakeReationForPartitionOid(estate->esfRelations, + estate->es_query_cxt, + result_relation_desc, + new_partId, + fake_part_rel, + insert_partition, + RowExclusiveLock); + fake_insert_relation = fake_part_rel; + if (bucketid != InvalidBktId) { + searchHBucketFakeRelation(estate->esfRelations, + estate->es_query_cxt, + fake_insert_relation, + bucketid, + fake_insert_relation); + } + + /* + * check constraints first if SQL has keyword IGNORE + */ + if (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(slot, estate, fake_insert_relation, insert_partition, &isgpi, + bucketid, &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(result_relation_desc)))); + return NULL; + } + /* delete the old tuple */ { - Partition old_partition = NULL; - Relation old_fake_relation = NULL; - TupleTableSlot* oldslot = NULL; - uint64 hash_del = 0; - - searchFakeReationForPartitionOid(estate->esfRelations, - estate->es_query_cxt, - result_relation_desc, - oldPartitionOid, - old_fake_relation, - old_partition, - RowExclusiveLock); - - if (bucketid != InvalidBktId) { - searchHBucketFakeRelation( - estate->esfRelations, estate->es_query_cxt, old_fake_relation, bucketid, old_fake_relation); - } - ldelete: /* Record updating behevior into user chain table */ if (result_relation_desc->rd_isblockchain) { @@ -2483,28 +2634,7 @@ ldelete: /* insert the new tuple */ { - Partition insert_partition = NULL; - Relation fake_insert_relation = NULL; - if (need_create_file) { - new_partId = AddNewIntervalPartition(result_relation_desc, tuple); - } - - searchFakeReationForPartitionOid(estate->esfRelations, - estate->es_query_cxt, - result_relation_desc, - new_partId, - fake_part_rel, - insert_partition, - RowExclusiveLock); - fake_insert_relation = fake_part_rel; - if (bucketid != InvalidBktId) { - searchHBucketFakeRelation(estate->esfRelations, - estate->es_query_cxt, - fake_insert_relation, - bucketid, - fake_insert_relation); - } if (result_relation_desc->rd_isblockchain) { MemoryContext old_context = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate)); tuple = set_user_tuple_hash((HeapTuple)tuple, fake_insert_relation); @@ -3245,7 +3375,8 @@ ModifyTableState* ExecInitModifyTable(ModifyTable* node, EState* estate, int efl if (result_rel_info->ri_FdwRoutine == NULL || result_rel_info->ri_FdwRoutine->GetFdwType == NULL || result_rel_info->ri_FdwRoutine->GetFdwType() != MOT_ORC) { #endif - ExecOpenIndices(result_rel_info, node->upsertAction != UPSERT_NONE); + ExecOpenIndices(result_rel_info, (node->upsertAction != UPSERT_NONE || + (estate->es_plannedstmt && estate->es_plannedstmt->hasIgnore))); #ifdef ENABLE_MOT } #endif diff --git a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp index ba61cd487..fd74f2c7d 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_insert.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_insert.cpp @@ -106,6 +106,7 @@ void InsertFusion::InitLocals(ParamListInfo params) { m_c_local.m_estate = CreateExecutorState(); m_c_local.m_estate->es_range_table = m_global->m_planstmt->rtable; + m_c_local.m_estate->es_plannedstmt = m_global->m_planstmt; m_local.m_reslot = MakeSingleTupleTableSlot(m_global->m_tupDesc); if (m_global->m_table_type == TAM_USTORE) { m_local.m_reslot->tts_tupslotTableAm = TAM_USTORE; @@ -200,7 +201,10 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i Assert(tuple != NULL); if (RELATION_IS_PARTITIONED(rel)) { m_c_local.m_estate->esfRelations = NULL; - partOid = heapTupleGetPartitionId(rel, tuple); + partOid = heapTupleGetPartitionId(rel, tuple, false, m_c_local.m_estate->es_plannedstmt->hasIgnore); + if (m_c_local.m_estate->es_plannedstmt->hasIgnore && partOid == InvalidOid) { + return 1; + } part = partitionOpen(rel, partOid, RowExclusiveLock); partRel = partitionGetRelation(rel, part); } @@ -225,7 +229,18 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i } if (rel->rd_att->constr) { - ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate); + /* + * If values violate constraints, directly return. + */ + if(!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { + return 1; + } + tuple = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate); + } } Relation destRel = RELATION_IS_PARTITIONED(rel) ? partRel : rel; Relation target_rel = (bucket_rel == NULL) ? destRel : bucket_rel; @@ -238,6 +253,34 @@ unsigned long InsertFusion::ExecInsert(Relation rel, ResultRelInfo* result_rel_i (void)MemoryContextSwitchTo(old_context); tableam_tops_free_tuple(tmp_tuple); } + + /* check unique constraint first if SQL has keyword IGNORE */ + bool isgpi = false; + ConflictInfoData conflictInfo; + Oid conflictPartOid = InvalidOid; + int2 conflictBucketid = InvalidBktId; + if (m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(m_local.m_reslot, m_c_local.m_estate, target_rel, part, &isgpi, bucketid, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(target_rel)))); + + /* clear before ended */ + tableam_tops_free_tuple(tuple); + (void)ExecClearTuple(m_local.m_reslot); + ExecCloseIndices(result_rel_info); + ExecDoneStepInFusion(m_c_local.m_estate); + if (bucket_rel != NULL) { + bucketCloseRelation(bucket_rel); + } + if (RELATION_IS_PARTITIONED(rel)) { + partitionClose(rel, part, RowExclusiveLock); + releaseDummyRelation(&partRel); + } + + return 1; + } + (void)tableam_tuple_insert(bucket_rel == NULL ? destRel : bucket_rel, tuple, mycid, 0, NULL); if (!RELATION_IS_PARTITIONED(rel)) { @@ -306,7 +349,7 @@ bool InsertFusion::execute(long max_rows, char* completionTag) InitResultRelInfo(result_rel_info, rel, 1, 0); if (result_rel_info->ri_RelationDesc->rd_rel->relhasindex) { - ExecOpenIndices(result_rel_info, false); + ExecOpenIndices(result_rel_info, true); } init_gtt_storage(CMD_INSERT, result_rel_info); diff --git a/src/gausskernel/runtime/opfusion/opfusion_update.cpp b/src/gausskernel/runtime/opfusion/opfusion_update.cpp index 4ab14eb98..d01044340 100644 --- a/src/gausskernel/runtime/opfusion/opfusion_update.cpp +++ b/src/gausskernel/runtime/opfusion/opfusion_update.cpp @@ -204,6 +204,7 @@ void UpdateFusion::InitLocals(ParamListInfo params) m_local.m_tmpvals = NULL; m_c_local.m_estate = CreateExecutorState(); m_c_local.m_estate->es_range_table = m_global->m_planstmt->rtable; + m_c_local.m_estate->es_plannedstmt = m_global->m_planstmt; m_local.m_reslot = MakeSingleTupleTableSlot(m_global->m_tupDesc); if (m_global->m_table_type == TAM_USTORE) { @@ -351,8 +352,30 @@ lreplace: } } - if (rel->rd_att->constr) - ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate); + if (rel->rd_att->constr) { + if (!ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate)) { + if (u_sess->utils_cxt.sql_ignore_strategy_val != SQL_OVERWRITE_NULL) { + return 0; + } + tup = ReplaceTupleNullCol(RelationGetDescr(result_rel_info->ri_RelationDesc), m_local.m_reslot); + /* Double check constraints in case that new val in column with not null constraints + * violated check constraints */ + ExecConstraints(result_rel_info, m_local.m_reslot, m_c_local.m_estate); + } + } + + /* Check unique constraints first if SQL has keyword IGNORE */ + bool isgpi = false; + ConflictInfoData conflictInfo; + Oid conflictPartOid = InvalidOid; + int2 conflictBucketid = InvalidBktId; + if (m_c_local.m_estate->es_plannedstmt && m_c_local.m_estate->es_plannedstmt->hasIgnore && + !ExecCheckIndexConstraints(m_local.m_reslot, m_c_local.m_estate, ledger_dest_rel, part, &isgpi, bucketid, + &conflictInfo, &conflictPartOid, &conflictBucketid)) { + ereport(WARNING, (errmsg("duplicate key value violates unique constraint in table \"%s\"", + RelationGetRelationName(ledger_dest_rel)))); + break; + } bool update_indexes = false; TupleTableSlot* oldslot = NULL; @@ -535,7 +558,7 @@ bool UpdateFusion::execute(long max_rows, char *completionTag) m_c_local.m_estate->es_output_cid = GetCurrentCommandId(true); if (result_rel_info->ri_RelationDesc->rd_rel->relhasindex) { - ExecOpenIndices(result_rel_info, false); + ExecOpenIndices(result_rel_info, true); } /* ******************************** diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 6bc3d9258..0743b984c 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -165,7 +165,7 @@ extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc, Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions); extern void heap_truncate_one_part(Relation rel , Oid partOid); -extern Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL = false); +extern Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL = false, bool canIgnore = false); extern Oid heapTupleGetSubPartitionId(Relation rel, void *tuple); extern void heap_truncate(List *relids); extern void heap_truncate_one_rel(Relation rel); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 39735080b..cab12f209 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -224,7 +224,7 @@ extern void InitResultRelInfo( ResultRelInfo* resultRelInfo, Relation resultRelationDesc, Index resultRelationIndex, int instrument_options); extern ResultRelInfo* ExecGetTriggerResultRel(EState* estate, Oid relid); extern bool ExecContextForcesOids(PlanState* planstate, bool* hasoids); -extern void ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate); +extern bool ExecConstraints(ResultRelInfo* resultRelInfo, TupleTableSlot* slot, EState* estate); extern ExecRowMark* ExecFindRowMark(EState* estate, Index rti); extern ExecAuxRowMark* ExecBuildAuxRowMark(ExecRowMark* erm, List* targetlist); extern TupleTableSlot* EvalPlanQual(EState* estate, EPQState* epqstate, Relation relation, Index rti, @@ -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 Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot); // AutoMutexLock // Auto object for non-recursive pthread_mutex_t lock diff --git a/src/include/fmgr.h b/src/include/fmgr.h index 89d9b582a..c00c94c53 100644 --- a/src/include/fmgr.h +++ b/src/include/fmgr.h @@ -155,6 +155,7 @@ typedef struct FunctionCallInfoData { fmNodePtr resultinfo; /* pass or return extra info about result */ Oid fncollation; /* collation for function to use */ bool isnull; /* function must set true if result is NULL */ + bool can_ignore; /* function can ignore overflow or underflow conditions for type transform function */ short nargs; /* # arguments actually passed */ Datum* arg; /* Arguments passed to function */ bool* argnull; /* T if arg[i] is actually NULL */ @@ -179,6 +180,7 @@ typedef struct FunctionCallInfoData { resultinfo = NULL; nargs = 0; isnull = false; + can_ignore = false; } } FunctionCallInfoData; @@ -449,7 +451,7 @@ typedef const Pg_magic_struct* (*PGModuleMagicFunction)(void); * directly-computed parameter list. Note that neither arguments nor result * are allowed to be NULL. */ -extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1); +extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1, bool can_ignore = false); extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2); extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3); extern Datum DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4); diff --git a/src/include/knl/knl_guc/knl_session_attr_sql.h b/src/include/knl/knl_guc/knl_session_attr_sql.h index 8fcb124ff..e68597374 100644 --- a/src/include/knl/knl_guc/knl_session_attr_sql.h +++ b/src/include/knl/knl_guc/knl_session_attr_sql.h @@ -183,6 +183,7 @@ typedef struct knl_session_attr_sql { char* behavior_compat_string; char* connection_info; char* retry_errcode_list; + char* sql_ignore_strategy_string; /* the vmoptions to start JVM */ char* pljava_vmoptions; int backslash_quote; diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index d79981d4d..57c98dc46 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -640,6 +640,8 @@ typedef struct knl_u_utils_context { bool enable_memory_context_control; syscalllock deleMemContextMutex; + + unsigned int sql_ignore_strategy_val; } knl_u_utils_context; typedef struct knl_u_security_context { diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 4b7754364..9a9008456 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -98,6 +98,7 @@ extern const uint32 SUPPORT_HASH_XLOG_VERSION_NUM; extern const uint32 PITR_INIT_VERSION_NUM; extern const uint32 PUBLICATION_INITIAL_DATA_VERSION_NAME; extern const uint32 CREATE_FUNCTION_DEFINER_VERSION; +extern const uint32 KEYWORD_IGNORE_COMPART_VERSION_NUM; extern void register_backend_version(uint32 backend_version); extern bool contain_backend_version(uint32 version_number); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 0e4623294..02235b2b9 100755 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -212,6 +212,7 @@ typedef struct ExprContext { bool have_vec_set_fun; bool* vec_fun_sel; // selection for vector set-result function. int current_row; + bool can_ignore; // indicates whether ERROR can be ignored when type casting } ExprContext; /* diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 7210c993e..31656eab5 100755 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -738,8 +738,8 @@ typedef enum NodeTag { T_SetHint, T_PlanCacheHint, T_NoExpandHint, + T_SqlIgnoreHint, T_NoGPCHint, - /* * pgfdw */ diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index f7ae33116..a62819bb1 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -424,6 +424,7 @@ typedef struct HintState { List* cache_plan_hint; /* enforce cplan or gplan */ List* no_expand_hint; /* forbid sub query pull-up */ List* no_gpc_hint; /* supress saving to global plan cache */ + bool sql_ignore_hint; /* hint of keyword ignore in SQL*/ } HintState; /* ---------------------- @@ -452,6 +453,7 @@ typedef struct InsertStmt { UpsertClause *upsertClause; /* DUPLICATE KEY UPDATE clause */ HintState *hintState; bool isRewritten; /* is this Stmt created by rewritter or end user? */ + bool hasIgnore; /* is this Stmt containing ignore keyword? */ } InsertStmt; /* ---------------------- @@ -482,6 +484,7 @@ typedef struct UpdateStmt { List *returningList; /* list of expressions to return */ WithClause *withClause; /* WITH clause */ HintState *hintState; + bool hasIgnore; /* is this Stmt containing ignore keyword? */ } UpdateStmt; /* ---------------------- @@ -1863,6 +1866,7 @@ typedef struct Query { bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */ bool hasRowSecurity; /* rewriter has applied some RLS policy */ bool hasSynonyms; /* has synonym mapping in rtable */ + bool hasIgnore; /* has keyword ignore in query string */ List* cteList; /* WITH list (of CommonTableExpr's) */ diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 992a60ff8..a4da22b11 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -72,6 +72,8 @@ typedef struct PlannedStmt { bool hasModifyingCTE; /* has insert|update|delete in WITH? */ + bool hasIgnore; /* is the executed query string has keyword ignore */ + bool canSetTag; /* do I set the command result tag? */ bool transientPlan; /* redo plan when TransactionXmin changes? */ diff --git a/src/include/optimizer/clauses.h b/src/include/optimizer/clauses.h index fa0103c76..b948e4a3a 100644 --- a/src/include/optimizer/clauses.h +++ b/src/include/optimizer/clauses.h @@ -100,7 +100,8 @@ extern Node* estimate_expression_value(PlannerInfo* root, Node* node, EState* es extern Query* inline_set_returning_function(PlannerInfo* root, RangeTblEntry* rte); extern bool filter_cstore_clause(PlannerInfo* root, Expr* clause); /* evaluate_expr used to be a static function */ -extern Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result_collation); +extern Expr* evaluate_expr(Expr* expr, Oid result_type, int32 result_typmod, Oid result_collation, + bool can_ignore = false); extern bool contain_var_unsubstitutable_functions(Node* clause); extern void distribute_qual_to_rels(PlannerInfo* root, Node* clause, bool is_deduced, bool below_outer_join, JoinType jointype, Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, diff --git a/src/include/parser/parse_hint.h b/src/include/parser/parse_hint.h index 88a3c009b..e4060aeda 100644 --- a/src/include/parser/parse_hint.h +++ b/src/include/parser/parse_hint.h @@ -58,6 +58,7 @@ #define HINT_CPLAN "Use_cplan" #define HINT_GPLAN "Use_gplan" #define HINT_NO_GPC "No_gpc" +#define HINT_SQL_IGNORE "Ignore_error" #define BLOCK_COMMENT_START "/*" #define BLOCK_COMMENT_END "*/" @@ -104,6 +105,7 @@ typedef enum HintKeyword { HINT_KEYWORD_SET, HINT_KEYWORD_CPLAN, HINT_KEYWORD_GPLAN, + HINT_KEYWORD_IGNORE, HINT_KEYWORD_NO_GPC, } HintKeyword; @@ -283,6 +285,12 @@ typedef struct NoGPCHint { Hint base; /* base hint */ } NoGPCHint; +/* sql ignore hints for storing keyword ignore in hint_string */ +typedef struct SqlIgnoreHint { + Hint base; /* base hint */ + bool sql_ignore_hint; +} SqlIgnoreHint; + typedef struct hintKeyword { const char* name; int value; diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index f808ca256..4e8cb38e3 100755 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -384,6 +384,11 @@ typedef enum { OPT_VECTOR_ENGINE } TryVectorEngineStrategy; +typedef enum { + SQL_IGNORE_NULL, + SQL_OVERWRITE_NULL +}SqlIgnoreHandleStrategy; + #define ENABLE_PRED_PUSH(root) \ ((PRED_PUSH & (uint)u_sess->attr.attr_sql.rewrite_rule) && permit_predpush(root)) diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h index c4be2550d..2cf3c1b1c 100644 --- a/src/include/utils/numeric.h +++ b/src/include/utils/numeric.h @@ -302,7 +302,7 @@ Numeric makeNumeric(NumericVar* var); extern Numeric make_result(NumericVar *var); extern void init_var_from_num(Numeric num, NumericVar* dest); extern void free_var(NumericVar *var); -extern bool numericvar_to_int64(const NumericVar* var, int64* result); +extern bool numericvar_to_int64(const NumericVar* var, int64* result, bool can_ignore = false); extern void int64_to_numericvar(int64 val, NumericVar *var); extern void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result); extern char *numeric_normalize(Numeric num); diff --git a/src/test/regress/expected/ignore/ignore_no_matched_partition.out b/src/test/regress/expected/ignore/ignore_no_matched_partition.out new file mode 100644 index 000000000..e4543f573 --- /dev/null +++ b/src/test/regress/expected/ignore/ignore_no_matched_partition.out @@ -0,0 +1,312 @@ +-- test for ignore error of no partition matched +create database sql_ignore_no_matched_partition_test dbcompatibility 'B'; +\c sql_ignore_no_matched_partition_test; +-- sqlbypass +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_ignore; +NOTICE: table "t_ignore" does not exist, skipping +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; +insert into t_ignore values(20000, 'abc'); +ERROR: inserted partition key does not map to any table partition +insert into t_ignore values(3000, 'abc'); +update t_ignore set col1 = 20000 where col1 = 3000; +ERROR: fail to update partitioned table "t_ignore" +DETAIL: new tuple does not map to any table partition +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +WARNING: inserted partition key does not map to any table partition +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +drop table if exists t_from; +NOTICE: table "t_from" does not exist, skipping +create table t_from (num int, content character varying(60)); +-- -- insert ignore from other tables with unmatchable rows +insert into t_from values(1000, 'valid row from t_from'); +insert into t_from values(20000, 'INVALID row from t_from'); +insert /*+ ignore_error */ into t_ignore select * from t_from; +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+----------------------- + 3000 | abc + 1000 | valid row from t_from +(2 rows) + +-- no sqlbypass +set enable_opfusion = off; +set enable_partition_opfusion = off; +insert into t_ignore values(1000, 'abc'); +insert into t_ignore values(30000, 'abc'); +ERROR: inserted partition key does not map to any table partition +update t_ignore set col1 = 30000 where col1 = 1000; +ERROR: fail to update partitioned table "t_ignore" +DETAIL: new tuple does not map to any table partition +select * from t_ignore; + col1 | col2 +------+----------------------- + 3000 | abc + 1000 | valid row from t_from + 1000 | abc +(3 rows) + +explain(costs off) insert /*+ ignore_error */ into t_ignore values(30000, 'abc'); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(30000, 'abc'); +WARNING: inserted partition key does not map to any table partition +update /*+ ignore_error */ t_ignore set col1 = 30000 where col1 = 1000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+----------------------- + 3000 | abc + 1000 | valid row from t_from + 1000 | abc +(3 rows) + +-- insert ignore from other tables with unmatchable rows +insert /*+ ignore_error */ into t_ignore select * from t_from; +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+----------------------- + 3000 | abc + 1000 | valid row from t_from + 1000 | abc + 1000 | valid row from t_from +(4 rows) + +-- test for subpartition table +drop table if exists ignore_range_range; +NOTICE: table "ignore_range_range" does not exist, skipping +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code VARCHAR2 ( 30 ) NOT NULL , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) +PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201901_b VALUES LESS THAN( '3' ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201902_b VALUES LESS THAN( '3' ) + ) +); +set enable_partition_opfusion = on; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '4', '1', 1); +WARNING: inserted partition key does not map to any table partition +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +update /*+ ignore_error */ ignore_range_range set dept_code = '4' where dept_code = '1'; +WARNING: fail to update partitioned table "ignore_range_range" +DETAIL: new tuple does not map to any table partition +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +delete from ignore_range_range; +set enable_partition_opfusion = off; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '4', '1', 1); +WARNING: inserted partition key does not map to any table partition +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +update /*+ ignore_error */ ignore_range_range set dept_code = '4' where dept_code = '1'; +WARNING: fail to update partitioned table "ignore_range_range" +DETAIL: new tuple does not map to any table partition +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +-- test for ustore table +drop table if exists t_ignore; +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) WITH(storage_type=ustore) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; +-- test for ustore table, opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +explain (costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+------ +(0 rows) + +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +-- test for ustore table, opfusion: off +delete from t_ignore; +set enable_opfusion = off; +set enable_partition_opfusion = off; +explain (costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+------ +(0 rows) + +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +-- test for segment table +drop table if exists t_ignore; +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) WITH(segment = on) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; +-- test for segment table, opfusion: on +set enable_partition_opfusion = on; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+------ +(0 rows) + +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +-- test for segment table, opfusion: off +set enable_partition_opfusion = off; +delete from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +WARNING: inserted partition key does not map to any table partition +select * from t_ignore; + col1 | col2 +------+------ +(0 rows) + +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +WARNING: fail to update partitioned table "t_ignore".new tuple does not map to any table partition. +select * from t_ignore; + col1 | col2 +------+------ + 3000 | abc +(1 row) + +set enable_opfusion = on; +set enable_partition_opfusion = off; +drop table t_ignore; +drop table t_from; +\c postgres +drop database if exists sql_ignore_no_matched_partition_test; diff --git a/src/test/regress/expected/ignore/ignore_not_null_constraints.out b/src/test/regress/expected/ignore/ignore_not_null_constraints.out new file mode 100644 index 000000000..cd2de052b --- /dev/null +++ b/src/test/regress/expected/ignore/ignore_not_null_constraints.out @@ -0,0 +1,1464 @@ +-- test for insert/update ignore. +create database sql_ignore_not_null_test dbcompatibility 'B'; +\c sql_ignore_not_null_test; +drop table if exists t_ignore; +NOTICE: table "t_ignore" does not exist, skipping +create table t_ignore(col1 int, col2 int not null, col3 varchar not null); +-- sqlbypass +set enable_opfusion = on; +-- test for condition without ignore +insert into t_ignore values(1, 1, 'abcdef'); +insert into t_ignore values(1, null, null); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +insert into t_ignore values(1, null, 'abcdef'); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, abcdef). +insert into t_ignore values(1, 1, null); +ERROR: null value in column "col3" violates not-null constraint +DETAIL: Failing row contains (1, 1, null). +insert into t_ignore values(1, null, null); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+-------- + 1 | 1 | abcdef +(1 row) + +update t_ignore set col2 = null, col3 = null; +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+-------- + 1 | 1 | abcdef +(1 row) + +-- test for condition with ignore +insert /*+ ignore_error */ into t_ignore values(1, 1, 'abcdef'); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +insert /*+ ignore_error */ into t_ignore values(1, null, 'abcdef'); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, abcdef). +insert /*+ ignore_error */ into t_ignore values(1, 1, null); +WARNING: null value in column "col3" violates not-null constraint +DETAIL: Failing row contains (1, 1, null). +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+-------- + 1 | 1 | abcdef + 1 | 1 | abcdef +(2 rows) + +update /*+ ignore_error */ t_ignore set col2 = null, col3 = null; +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+-------- + 1 | 1 | abcdef + 1 | 1 | abcdef +(2 rows) + +-- insert ignore from other tables with null +drop table if exists t_from; +NOTICE: table "t_from" does not exist, skipping +create table t_from (col1 int, col2 int, col3 varchar); +insert into t_from values(9,9,'row from others'); +insert into t_from values(1, null, null); +insert /*+ ignore_error */ into t_ignore select * from t_from; +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others +(3 rows) + +-- test for null replacement +set sql_ignore_strategy = 'overwrite_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | +(4 rows) + +set sql_ignore_strategy = 'ignore_null'; +-- no bypass +set enable_opfusion = off; +-- test for condition without ignore +insert into t_ignore values(1, 1, 'abcdef'); +insert into t_ignore values(1, null, null); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +insert into t_ignore values(1, null, 'abcdef'); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, abcdef). +insert into t_ignore values(1, 1, null); +ERROR: null value in column "col3" violates not-null constraint +DETAIL: Failing row contains (1, 1, null). +insert into t_ignore values(1, null, null); +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef +(5 rows) + +update t_ignore set col2 = null, col3 = null; +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef +(5 rows) + +-- test for condition with ignore +insert /*+ ignore_error */ into t_ignore values(1, 1, 'abcdef'); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +insert /*+ ignore_error */ into t_ignore values(1, null, 'abcdef'); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, abcdef). +insert /*+ ignore_error */ into t_ignore values(1, 1, null); +WARNING: null value in column "col3" violates not-null constraint +DETAIL: Failing row contains (1, 1, null). +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef + 1 | 1 | abcdef +(6 rows) + +update t_ignore set col2 = null, col3 = null; +ERROR: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef + 1 | 1 | abcdef +(6 rows) + +-- insert ignore from other tables with null +insert /*+ ignore_error */ into t_ignore select * from t_from; +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others +(7 rows) + +-- test for null replacement +set sql_ignore_strategy = 'overwrite_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(1, null, null); +WARNING: null value in column "col2" violates not-null constraint +DETAIL: Failing row contains (1, null, null). +select * from t_ignore; + col1 | col2 | col3 +------+------+----------------- + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | + 1 | 1 | abcdef + 1 | 1 | abcdef + 9 | 9 | row from others + 1 | 0 | +(8 rows) + +set sql_ignore_strategy = 'ignore_null'; +-- test for overwriting null into "zero" of specific type +set sql_ignore_strategy = 'overwrite_null'; +-- timestamp +create table t_timestamp(c timestamp not null); +insert /*+ ignore_error */ into t_timestamp values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_timestamp; +--?.* +--?.* +--?.* +(1 row) + +insert into t_timestamp values('2022-06-01 17:26:59.846448'); +update /*+ ignore_error */ t_timestamp set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_timestamp; +--?.* +--?.* +--?.* +--?.* +(2 rows) + +-- timetz +create table t_timetz(c timetz not null); +insert /*+ ignore_error */ into t_timetz values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_timetz; + c +------------- + 00:00:00-07 +(1 row) + +insert into t_timetz values('00:00:01+08'); +update /*+ ignore_error */ t_timetz set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_timetz; + c +------------- + 00:00:00-07 + 00:00:00-07 +(2 rows) + +-- time +create table t_time(c time not null); +insert /*+ ignore_error */ into t_time values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_time; + c +---------- + 00:00:00 +(1 row) + +insert into t_time values('00:00:00'); +update /*+ ignore_error */ t_time set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_time; + c +---------- + 00:00:00 + 00:00:00 +(2 rows) + +-- interval +create table t_interval(c interval not null); +insert /*+ ignore_error */ into t_interval values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_interval; + c +----- + @ 0 +(1 row) + +insert into t_interval values('00:00:01'); +update /*+ ignore_error */ t_interval set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_interval; + c +----- + @ 0 + @ 0 +(2 rows) + +-- tinterval +create table t_tinterval(c tinterval not null); +insert /*+ ignore_error */ into t_tinterval values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_tinterval; + c +----------------------------------------------------------------- + ["Thu Jan 01 00:00:00 1970 PST" "Thu Jan 01 00:00:00 1970 PST"] +(1 row) + +update /*+ ignore_error */ t_tinterval set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_tinterval; + c +----------------------------------------------------------------- + ["Thu Jan 01 00:00:00 1970 PST" "Thu Jan 01 00:00:00 1970 PST"] +(1 row) + +-- smalldatetime +create table t_smalldatetime(c smalldatetime not null); +insert /*+ ignore_error */ into t_smalldatetime values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_smalldatetime; + c +-------------------------- + Thu Jan 01 08:00:00 1970 +(1 row) + +insert into t_smalldatetime values('1991-01-01 08:00:00'); +update /*+ ignore_error */ t_smalldatetime set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_smalldatetime; + c +-------------------------- + Thu Jan 01 08:00:00 1970 + Thu Jan 01 08:00:00 1970 +(2 rows) + +-- date +create table t_date(c date not null); +insert /*+ ignore_error */ into t_date values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_date; + c +------------ + 01-01-1970 +(1 row) + +insert into t_date values('1991-01-01 08:00:00'); +update /*+ ignore_error */ t_date set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_date; + c +------------ + 01-01-1970 + 01-01-1970 +(2 rows) + +-- uuid +create table t_uuid(c uuid not null); +insert /*+ ignore_error */ into t_uuid values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_uuid; + c +-------------------------------------- + 00000000-0000-0000-0000-000000000000 +(1 row) + +insert into t_uuid values('aaaaaaaa-0000-0000-0000-000000000000'); +update /*+ ignore_error */ t_uuid set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_uuid; + c +-------------------------------------- + 00000000-0000-0000-0000-000000000000 + 00000000-0000-0000-0000-000000000000 +(2 rows) + +-- name +create table t_name(c name not null); +insert /*+ ignore_error */ into t_name values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_name; + c +--- + +(1 row) + +insert into t_name values('abc'); +update /*+ ignore_error */ t_name set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_name; + c +--- + + +(2 rows) + +-- point +create table t_point(c point not null); +insert /*+ ignore_error */ into t_point values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_point; + c +------- + (0,0) +(1 row) + +insert into t_point values('(1,1)'); +update /*+ ignore_error */ t_point set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_point; + c +------- + (0,0) + (0,0) +(2 rows) + +-- path +create table t_path(c path not null); +insert /*+ ignore_error */ into t_path values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_path; + c +--------- + ((0,0)) +(1 row) + +insert into t_path values('((1,1))'); +update /*+ ignore_error */ t_path set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_path; + c +--------- + ((0,0)) + ((0,0)) +(2 rows) + +-- polygon +create table t_polygon(c polygon not null); +insert /*+ ignore_error */ into t_polygon values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_polygon; + c +--------- + ((0,0)) +(1 row) + +insert into t_polygon values('((1,1))'); +update /*+ ignore_error */ t_polygon set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_polygon; + c +--------- + ((0,0)) + ((0,0)) +(2 rows) + +-- circle +create table t_circle(c circle not null); +insert /*+ ignore_error */ into t_circle values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_circle; + c +----------- + <(0,0),0> +(1 row) + +insert into t_circle values('<(1,1),1>'); +update /*+ ignore_error */ t_circle set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_circle; + c +----------- + <(0,0),0> + <(0,0),0> +(2 rows) + +-- box +create table t_box(c box not null); +insert /*+ ignore_error */ into t_box values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_box; + c +------------- + (0,0),(0,0) +(1 row) + +insert into t_box values('(1,1),(2,2)'); +update /*+ ignore_error */ t_box set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_box; + c +------------- + (0,0),(0,0) + (0,0),(0,0) +(2 rows) + +-- json +create table t_json(c json not null); +insert /*+ ignore_error */ into t_json values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_json; + c +--- + 0 +(1 row) + +insert into t_json values('111'); +update /*+ ignore_error */ t_json set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_json; + c +--- + 0 + 0 +(2 rows) + +-- jsonb +create table t_jsonb(c jsonb not null); +insert /*+ ignore_error */ into t_jsonb values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_jsonb; + c +--- + 0 +(1 row) + +insert into t_jsonb values('111'); +update /*+ ignore_error */ t_jsonb set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_jsonb; + c +--- + 0 + 0 +(2 rows) + +-- bit +create table t_bit(c bit not null); +insert /*+ ignore_error */ into t_bit values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bit; + c +--- + +(1 row) + +insert into t_bit values('1'); +update /*+ ignore_error */ t_bit set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bit; + c +--- + + +(2 rows) + +-- tinyint +create table t_tinyint(c tinyint not null); +insert /*+ ignore_error */ into t_tinyint values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_tinyint; + c +--- + 0 +(1 row) + +insert into t_tinyint values('10'); +update /*+ ignore_error */ t_tinyint set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_tinyint; + c +--- + 0 + 0 +(2 rows) + +-- smallint +create table t_smallint(c smallint not null); +insert /*+ ignore_error */ into t_smallint values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_smallint; + c +--- + 0 +(1 row) + +insert into t_smallint values('123'); +update /*+ ignore_error */ t_smallint set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_smallint; + c +--- + 0 + 0 +(2 rows) + +-- int +create table t_int(c int not null); +insert /*+ ignore_error */ into t_int values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_int; + c +--- + 0 +(1 row) + +insert into t_int values(9999); +update /*+ ignore_error */ t_int set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_int; + c +--- + 0 + 0 +(2 rows) + +-- bigint +create table t_bigint(c bigint not null); +insert /*+ ignore_error */ into t_bigint values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bigint; + c +--- + 0 +(1 row) + +insert into t_bigint values(9999999999999999); +update /*+ ignore_error */ t_bigint set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bigint; + c +--- + 0 + 0 +(2 rows) + +-- float +create table t_float(c float not null); +insert /*+ ignore_error */ into t_float values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_float; + c +--- + 0 +(1 row) + +insert into t_float values(123.99); +update /*+ ignore_error */ t_float set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_float; + c +--- + 0 + 0 +(2 rows) + +-- float8 +create table t_float8(c float8 not null); +insert /*+ ignore_error */ into t_float8 values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_float8; + c +--- + 0 +(1 row) + +insert into t_float8 values(123.99); +update /*+ ignore_error */ t_float8 set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_float8; + c +--- + 0 + 0 +(2 rows) + +-- numeric +create table t_numeric(c numeric not null); +insert /*+ ignore_error */ into t_numeric values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_numeric; + c +--- + 0 +(1 row) + +insert into t_numeric values(123.99); +update /*+ ignore_error */ t_numeric set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_numeric; + c +--- + 0 + 0 +(2 rows) + +-- serial +create table t_serial(c serial not null); +NOTICE: CREATE TABLE will create implicit sequence "t_serial_c_seq" for serial column "t_serial.c" +insert /*+ ignore_error */ into t_serial values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_serial; + c +--- + 0 +(1 row) + +insert into t_serial values(123); +update /*+ ignore_error */ t_serial set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_serial; + c +--- + 0 + 0 +(2 rows) + +-- bool +create table t_bool(c bool not null); +insert /*+ ignore_error */ into t_bool values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bool; + c +--- + f +(1 row) + +insert into t_bool values(true); +update /*+ ignore_error */ t_bool set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_bool; + c +--- + f + f +(2 rows) + +-- char(n) +create table t_charn(c char(6) not null); +insert /*+ ignore_error */ into t_charn values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_charn; + c +--- + +(1 row) + +insert into t_charn values('abc'); +update /*+ ignore_error */ t_charn set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_charn; + c +--- + + +(2 rows) + +-- varchar(n) +create table t_varcharn(c varchar(6) not null); +insert /*+ ignore_error */ into t_varcharn values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_varcharn; + c +--- + +(1 row) + +insert into t_varcharn values('xxxxxx'); +update /*+ ignore_error */ t_varcharn set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_varcharn; + c +--- + + +(2 rows) + +-- text +create table t_text(c text not null); +insert /*+ ignore_error */ into t_text values (null); +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_text; + c +--- + +(1 row) + +insert into t_text values('xxxxxx'); +update /*+ ignore_error */ t_text set c = null; +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +WARNING: null value in column "c" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_text; + c +--- + + +(2 rows) + +-- mixture +drop table if exists t_mix; +NOTICE: table "t_mix" does not exist, skipping +create table t_mix +( + c1 int, + c2 bigint not null, + c3 varchar(6) not null, + c4 bool not null +); +insert /*+ ignore_error */ into t_mix values(1, null, null, null); +WARNING: null value in column "c2" violates not-null constraint +DETAIL: Failing row contains (1, null, null, null). +insert /*+ ignore_error */ into t_mix values(2, 2, null, null); +WARNING: null value in column "c3" violates not-null constraint +DETAIL: Failing row contains (2, 2, null, null). +select * from t_mix; + c1 | c2 | c3 | c4 +----+----+----+---- + 1 | 0 | | f + 2 | 2 | | f +(2 rows) + +insert into t_mix values(2, 2, 'abced', true); +update /*+ ignore_error */ t_mix set c1 = 9, c2 = null, c3 = null, c4 = null; +WARNING: null value in column "c2" violates not-null constraint +DETAIL: Failing row contains (9, null, null, null). +WARNING: null value in column "c2" violates not-null constraint +DETAIL: Failing row contains (9, null, null, null). +WARNING: null value in column "c2" violates not-null constraint +DETAIL: Failing row contains (9, null, null, null). +select * from t_mix; + c1 | c2 | c3 | c4 +----+----+----+---- + 9 | 0 | | f + 9 | 0 | | f + 9 | 0 | | f +(3 rows) + +drop table if exists t_mix; +-- test for mixture of not null constraints and check constraints +create table t_mix(num int not null check(num > 5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +ERROR: new row for relation "t_mix" violates check constraint "t_mix_num_check" +DETAIL: N/A +select * from t_mix; + num +----- +(0 rows) + +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +ERROR: new row for relation "t_mix" violates check constraint "t_mix_num_check" +DETAIL: N/A +select * from t_mix; + num +----- +(0 rows) + +drop table if exists t_mix; +create table t_mix(num int not null check(num > -5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_mix; + num +----- + 0 +(1 row) + +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_mix; + num +----- + 0 + 0 +(2 rows) + +drop table if exists t_mix; +create table t_mix(content text not null check(length(content) > 5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "content" violates not-null constraint +DETAIL: Failing row contains (null). +ERROR: new row for relation "t_mix" violates check constraint "t_mix_content_check" +DETAIL: N/A +select * from t_mix; + content +--------- +(0 rows) + +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +WARNING: null value in column "content" violates not-null constraint +DETAIL: Failing row contains (null). +ERROR: new row for relation "t_mix" violates check constraint "t_mix_content_check" +DETAIL: N/A +select * from t_mix; + content +--------- +(0 rows) + +drop table if exists t_mix; +-- test for partition table with not null constraint +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_not_null_key_partition; +NOTICE: table "t_not_null_key_partition" does not exist, skipping +CREATE TABLE t_not_null_key_partition +( + num integer NOT NULL, + ca_city character varying(60) +) PARTITION BY RANGE (num) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000), + PARTITION P4 VALUES LESS THAN(20000), + PARTITION P5 VALUES LESS THAN(25000), + PARTITION P6 VALUES LESS THAN(30000), + PARTITION P7 VALUES LESS THAN(40000) +); +insert into t_not_null_key_partition values(1, 'shenzhen'); +select * from t_not_null_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen +(1 row) + +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_not_null_key_partition values (null); + QUERY PLAN +------------------------------------ + [Bypass] + Insert on t_not_null_key_partition + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_not_null_key_partition values (null); +WARNING: inserted partition key does not map to any table partition +select * from t_not_null_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen +(1 row) + +update /*+ ignore_error */ t_not_null_key_partition set num = null; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null, shenzhen). +select * from t_not_null_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen +(1 row) + +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_not_null_key_partition values (null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null, null). +select * from t_not_null_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 0 | +(2 rows) + +update /*+ ignore_error */ t_not_null_key_partition set num = null; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null, shenzhen). +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null, null). +select * from t_not_null_key_partition; + num | ca_city +-----+---------- + 0 | shenzhen + 0 | +(2 rows) + +-- test for subpartition table +drop table if exists ignore_range_range; +NOTICE: table "ignore_range_range" does not exist, skipping +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code int NOT NULL , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) + PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( -5 ), + SUBPARTITION p_201901_b VALUES LESS THAN( 1 ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( -5 ), + SUBPARTITION p_201902_b VALUES LESS THAN( 1 ) + ) +); +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +-- sql_ignore_strategy: ignore_null +set sql_ignore_strategy = 'ignore_null'; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- +(0 rows) + +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | -3 | 1 | 1 +(1 row) + +-- sql_ignore_strategy: overwrite_null +delete from ignore_range_range; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 0 | 1 | 1 +(1 row) + +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 0 | 1 | 1 + 201901 | 0 | 1 | 1 +(2 rows) + +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; +-- sql_ignore_strategy: ignore_null +set sql_ignore_strategy = 'ignore_null'; +delete from ignore_range_range; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- +(0 rows) + +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | -3 | 1 | 1 +(1 row) + +-- sql_ignore_strategy: overwrite_null +set sql_ignore_strategy = 'overwrite_null'; +delete from ignore_range_range; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 0 | 1 | 1 +(1 row) + +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +WARNING: null value in column "dept_code" violates not-null constraint +DETAIL: Failing row contains (201901, null, 1, 1). +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 0 | 1 | 1 + 201901 | 0 | 1 | 1 +(2 rows) + +delete from ignore_range_range; +-- test for ustore table +drop table if exists t_ignore; +create table t_ignore(num int not null) with (storage_type = ustore); +-- opfusion: on +set enable_opfusion = on; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- +(0 rows) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 1 +(1 row) + +delete from t_ignore; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 +(1 row) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 + 0 +(2 rows) + +-- opfusion: off +delete from t_ignore; +set enable_opfusion = off; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- +(0 rows) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 1 +(1 row) + +delete from t_ignore; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 +(1 row) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 + 0 +(2 rows) + +-- test for segment table +drop table if exists t_ignore; +create table t_ignore(num int not null) with (segment = on); +-- test for segment table, opfusion: on +set enable_opfusion = on; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- +(0 rows) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 1 +(1 row) + +set sql_ignore_strategy = 'overwrite_null'; +delete from t_ignore; +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 +(1 row) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 + 0 +(2 rows) + +-- test for segment table, opfusion: off +set enable_opfusion = off; +set sql_ignore_strategy = 'ignore_null'; +delete from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- +(0 rows) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 1 +(1 row) + +set sql_ignore_strategy = 'overwrite_null'; +delete from t_ignore; +insert /*+ ignore_error */ into t_ignore values(null); +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 +(1 row) + +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +WARNING: null value in column "num" violates not-null constraint +DETAIL: Failing row contains (null). +select * from t_ignore; + num +----- + 0 + 0 +(2 rows) + +-- restore context +\c postgres +drop database if exists sql_ignore_not_null_test; diff --git a/src/test/regress/expected/ignore/ignore_type_transform.out b/src/test/regress/expected/ignore/ignore_type_transform.out new file mode 100644 index 000000000..c68356110 --- /dev/null +++ b/src/test/regress/expected/ignore/ignore_type_transform.out @@ -0,0 +1,795 @@ +create database sql_ignore_type_transform_test dbcompatibility 'B'; +\c sql_ignore_type_transform_test; +-- test for tinyint +drop table if exists t; +NOTICE: table "t" does not exist, skipping +create table t(num tinyint); +insert into t values(10000); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t values(-10000); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t values(100); +insert into t values(-100); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(10000); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(-10000); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(100); +insert /*+ ignore_error */ into t values(-100); +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t; + num +----- + 100 + 255 + 0 + 100 + 0 +(5 rows) + +update /*+ ignore_error */ t set num = 100000 where num = 100; +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t; + num +----- + 255 + 0 + 0 + 255 + 255 +(5 rows) + +-- insert numeric table into tinyint table +drop table if exists t_tinyint; +NOTICE: table "t_tinyint" does not exist, skipping +drop table if exists t_numeric; +NOTICE: table "t_numeric" does not exist, skipping +create table t_tinyint(num tinyint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_tinyint select num from t_numeric; +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: tinyint out of range +CONTEXT: referenced column: num +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t_tinyint; + num +----- + 255 + 0 +(2 rows) + +-- test for smallint +drop table if exists t; +create table t(num smallint); +insert into t values(100000); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t values(-100000); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t values(10000); +insert into t values(-10000); +insert /*+ ignore_error */ into t values(100000); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(-100000); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(10000); +insert /*+ ignore_error */ into t values(-10000); +select * from t; + num +-------- + 10000 + -10000 + 32767 + -32768 + 10000 + -10000 +(6 rows) + +update /*+ ignore_error */ t set num = 1000000 where num = 10000; +WARNING: smallint out of range +CONTEXT: referenced column: num +select * from t; + num +-------- + -10000 + 32767 + -32768 + -10000 + 32767 + 32767 +(6 rows) + +-- insert numeric table into smallint table +drop table if exists t_smallint; +NOTICE: table "t_smallint" does not exist, skipping +drop table if exists t_numeric; +create table t_smallint(num smallint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_smallint select num from t_numeric; +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: smallint out of range +CONTEXT: referenced column: num +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: smallint out of range +CONTEXT: referenced column: num +select * from t_smallint; + num +-------- + 32767 + -32768 +(2 rows) + +-- test for int +drop table if exists t; +create table t(num int); +insert into t values(10000000000); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t values(-10000000000); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t values(1000000); +insert into t values(-1000000); +insert /*+ ignore_error */ into t values(10000000000); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(-10000000000); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(1000000); +insert /*+ ignore_error */ into t values(-1000000); +select * from t; + num +------------- + 1000000 + -1000000 + 2147483647 + -2147483648 + 1000000 + -1000000 +(6 rows) + +update /*+ ignore_error */ t set num = 99999999999999999999 where num = 1000000; +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: integer out of range +CONTEXT: referenced column: num +select * from t; + num +------------- + -1000000 + 2147483647 + -2147483648 + -1000000 + 2147483647 + 2147483647 +(6 rows) + +-- insert numeric table into int table +drop table if exists t_int; +NOTICE: table "t_int" does not exist, skipping +drop table if exists t_numeric; +create table t_int(num int); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_int select num from t_numeric; +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: integer out of range +CONTEXT: referenced column: num +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: integer out of range +CONTEXT: referenced column: num +select * from t_int; + num +------------- + 2147483647 + -2147483648 +(2 rows) + +-- test for bigint +drop table if exists t; +create table t(num bigint); +insert into t values(847329847839274398574389574398579834759384504385094386073456058984); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t values(-439058439498375898437567893745893275984375984375984375984345498759438); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t values(10000000::numeric); +insert into t values(-10000000::numeric); +insert /*+ ignore_error */ into t values(847329847839274398574389574398579834759384504385094386073456058984); +WARNING: value out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(-439058439498375898437567893745893275984375984375984375984345498759438); +WARNING: value out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t values(10000000::numeric); +insert /*+ ignore_error */ into t values(-10000000::numeric); +select * from t; + num +---------------------- + 10000000 + -10000000 + 9223372036854775807 + -9223372036854775808 + 10000000 + -10000000 +(6 rows) + +update /*+ ignore_error */ t set num = 99999999999999999999999999999999999999999999999999999999999999999999999999 where num = 10000000; +WARNING: value out of range +CONTEXT: referenced column: num +select * from t; + num +---------------------- + -10000000 + 9223372036854775807 + -9223372036854775808 + -10000000 + 9223372036854775807 + 9223372036854775807 +(6 rows) + +-- insert numeric table into bigint table +drop table if exists t_bigint; +NOTICE: table "t_bigint" does not exist, skipping +drop table if exists t_numeric; +create table t_bigint(num bigint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_bigint select num from t_numeric; +WARNING: value out of range +CONTEXT: referenced column: num +WARNING: value out of range +CONTEXT: referenced column: num +select * from t_bigint; + num +---------------------- + 9223372036854775807 + -9223372036854775808 +(2 rows) + +-- insert int table into tinyint table +drop table if exists t_int; +drop table if exists t_tinyint; +create table t_int(num int); +create table t_tinyint(num tinyint); +insert into t_int values(10000); +insert into t_int values(-10000); +insert /*+ ignore_error */ into t_tinyint select num from t_int; +WARNING: tinyint out of range +CONTEXT: referenced column: num +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t_tinyint; + num +----- + 255 + 0 +(2 rows) + +-- insert int table into smallint table +drop table if exists t_int; +drop table if exists t_smallint; +create table t_int(num int); +create table t_smallint(num smallint); +insert into t_int values(1000000); +insert into t_int values(-1000000); +insert /*+ ignore_error */ into t_smallint select num from t_int; +WARNING: smallint out of range +CONTEXT: referenced column: num +WARNING: smallint out of range +CONTEXT: referenced column: num +select * from t_smallint; + num +-------- + 32767 + -32768 +(2 rows) + +-- test for float4 to tinyint +drop table if exists t_tinyint; +create table t_tinyint(num tinyint); +insert into t_tinyint values (10000.023::float4); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t_tinyint values (-10000.023::float4); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t_tinyint values (123.023::float4); +insert into t_tinyint values (-123.023::float4); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (10000.023::float4); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (-10000.023::float4); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (123.023::float4); +insert /*+ ignore_error */ into t_tinyint values (-123.023::float4); +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t_tinyint; + num +----- + 123 + 255 + 0 + 123 + 0 +(5 rows) + +-- test for float4 to smallint +drop table if exists t_smallint; +create table t_smallint(num smallint); +insert into t_smallint values (1000000.023::float4); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t_smallint values (-1000000.023::float4); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t_smallint values (10000.023::float4); +insert into t_smallint values (-10000.023::float4); +insert /*+ ignore_error */ into t_smallint values (1000000.023::float4); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_smallint values (-1000000.023::float4); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_smallint values (10000.023::float4); +insert /*+ ignore_error */ into t_smallint values (-10000.023::float4); +select * from t_smallint; + num +-------- + 10000 + -10000 + 32767 + -32768 + 10000 + -10000 +(6 rows) + +-- test for float4 to int +drop table if exists t_int; +create table t_int(num int); +insert into t_int values (72348787598743985743895.023::float4); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t_int values (-72348787598743985743895.023::float4); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t_int values (123123.023::float4); +insert into t_int values (-123123.023::float4); +insert /*+ ignore_error */ into t_int values (72348787598743985743895.023::float4); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_int values (-72348787598743985743895.023::float4); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_int values (123123.023::float4); +insert /*+ ignore_error */ into t_int values (-123123.023::float4); +select * from t_int; + num +------------- + 123123 + -123123 + 2147483647 + -2147483648 + 123123 + -123123 +(6 rows) + +-- test for float4 to bigint +drop table if exists t_bigint; +create table t_bigint(num bigint); +insert into t_bigint values (238947289573489758943455436587549686.023::float4); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t_bigint values (-238947289573489758943455436587549686.023::float4); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t_bigint values (100000.023::float4); +insert into t_bigint values (-100000.023::float4); +insert /*+ ignore_error */ into t_bigint values (238947289573489758943455436587549686.023::float4); +WARNING: bigint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_bigint values (-238947289573489758943455436587549686.023::float4); +WARNING: bigint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_bigint values (100000.023::float4); +insert /*+ ignore_error */ into t_bigint values (-100000.023::float4); +select * from t_bigint; + num +---------------------- + 100000 + -100000 + 9223372036854775807 + -9223372036854775808 + 100000 + -100000 +(6 rows) + +-- test for float8 to tinyint +drop table if exists t_tinyint; +create table t_tinyint(num tinyint); +insert into t_tinyint values (238947289573489758943455436587549686.023::float8); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t_tinyint values (-238947289573489758943455436587549686.023::float8); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert into t_tinyint values (100.123::float8); +insert into t_tinyint values (-100.123::float8); +ERROR: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (238947289573489758943455436587549686.023::float8); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (-238947289573489758943455436587549686.023::float8); +WARNING: tinyint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_tinyint values (100.123::float8); +insert /*+ ignore_error */ into t_tinyint values (-100.123::float8); +WARNING: tinyint out of range +CONTEXT: referenced column: num +select * from t_tinyint; + num +----- + 100 + 255 + 0 + 100 + 0 +(5 rows) + +-- test for float8 to smallint +drop table if exists t_smallint; +create table t_smallint(num smallint); +insert into t_smallint values (238947289573489758943455436587549686.023::float8); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t_smallint values (-238947289573489758943455436587549686.023::float8); +ERROR: smallint out of range +CONTEXT: referenced column: num +insert into t_smallint values (100.023::float8); +insert into t_smallint values (-100.023::float8); +insert /*+ ignore_error */ into t_smallint values (238947289573489758943455436587549686.023::float8); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_smallint values (-238947289573489758943455436587549686.023::float8); +WARNING: smallint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_smallint values (100.023::float8); +insert /*+ ignore_error */ into t_smallint values (-100.023::float8); +select * from t_smallint; + num +-------- + 100 + -100 + -32768 + 32767 + 100 + -100 +(6 rows) + +-- test for float8 to int +drop table if exists t_int; +create table t_int(num int); +insert into t_int values (23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t_int values (-23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +ERROR: integer out of range +CONTEXT: referenced column: num +insert into t_int values (123.023::float8); +insert into t_int values (-123.023::float8); +insert /*+ ignore_error */ into t_int values (23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_int values (-23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +WARNING: integer out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_int values (123.023::float8); +insert /*+ ignore_error */ into t_int values (-123.023::float8); +select * from t_int; + num +------------- + 123 + -123 + 2147483647 + -2147483648 + 123 + -123 +(6 rows) + +-- test for float8 to bigint +drop table if exists t_bigint; +create table t_bigint(num bigint); +insert into t_bigint values (238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t_bigint values (-238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +ERROR: bigint out of range +CONTEXT: referenced column: num +insert into t_bigint values (123.123::float8); +insert into t_bigint values (-123.123::float8); +insert /*+ ignore_error */ into t_bigint values (238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +WARNING: bigint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_bigint values (-238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +WARNING: bigint out of range +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_bigint values (123.123::float8); +insert /*+ ignore_error */ into t_bigint values (-123.123::float8); +select * from t_bigint; + num +---------------------- + 123 + -123 + 9223372036854775807 + -9223372036854775808 + 123 + -123 +(6 rows) + +-- test for float8 to float4 +drop table if exists t_float4; +NOTICE: table "t_float4" does not exist, skipping +create table t_float4(num float4); +insert into t_float4 values (1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +ERROR: value out of range: overflow +CONTEXT: referenced column: num +insert into t_float4 values (-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +ERROR: value out of range: overflow +CONTEXT: referenced column: num +insert into t_float4 values(123.123::float8); +insert into t_float4 values(-123.123::float8); +insert /*+ ignore_error */ into t_float4 values (1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +WARNING: value out of range: overflow +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_float4 values (-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +WARNING: value out of range: overflow +CONTEXT: referenced column: num +insert /*+ ignore_error */ into t_float4 values(123.123::float8); +insert /*+ ignore_error */ into t_float4 values(-123.123::float8); +select * from t_float4; + num +------------- + 123.123 + -123.123 + 3.40282e+38 + 1.17549e-38 + 123.123 + -123.123 +(6 rows) + +-- test for numeric to float4 +drop table if exists t_numeric; +drop table if exists t_float4; +create table t_numeric(num numeric); +create table t_float4(num float4); +insert into t_numeric values(1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984); +insert into t_numeric values(-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984); +insert /*+ ignore_error */ into t_float4 select num from t_numeric; +WARNING: value out of range: overflow +CONTEXT: referenced column: num +WARNING: value out of range: overflow +CONTEXT: referenced column: num +select * from t_float4; + num +------------- + 3.40282e+38 + 3.40282e+38 +(2 rows) + +-- test for char(n) converting +drop table if exists t_char; +NOTICE: table "t_char" does not exist, skipping +drop table if exists t_text; +NOTICE: table "t_text" does not exist, skipping +create table t_char(cont char(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_char select cont from t_text; +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +select * from t_char; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for varchar(n) converting +drop table if exists t_varchar; +NOTICE: table "t_varchar" does not exist, skipping +drop table if exists t_text; +create table t_varchar(cont varchar(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_varchar select cont from t_text; +WARNING: value too long for type character varying(6) +CONTEXT: referenced column: cont +WARNING: value too long for type character varying(6) +CONTEXT: referenced column: cont +select * from t_varchar; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for character(n) converting +drop table if exists t_character; +NOTICE: table "t_character" does not exist, skipping +drop table if exists t_text; +create table t_character(cont character(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_character select cont from t_text; +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +select * from t_character; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for nchar(n) converting +drop table if exists t_nchar; +NOTICE: table "t_nchar" does not exist, skipping +drop table if exists t_text; +create table t_nchar(cont nchar(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nchar select cont from t_text; +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +WARNING: value too long for type character(6) +CONTEXT: referenced column: cont +select * from t_nchar; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for character converting +drop table if exists t_character; +drop table if exists t_text; +create table t_character(cont character); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_character select cont from t_text; +WARNING: value too long for type character(1) +CONTEXT: referenced column: cont +WARNING: value too long for type character(1) +CONTEXT: referenced column: cont +WARNING: value too long for type character(1) +CONTEXT: referenced column: cont +select * from t_character; + cont +------ + a + a + 1 +(3 rows) + +-- test for varchar2(n) converting +drop table if exists t_varchar2; +NOTICE: table "t_varchar2" does not exist, skipping +drop table if exists t_text; +create table t_varchar2(cont varchar2(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_varchar2 select cont from t_text; +WARNING: value too long for type character varying(6) +CONTEXT: referenced column: cont +WARNING: value too long for type character varying(6) +CONTEXT: referenced column: cont +select * from t_varchar2; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for nvarchar2(n) converting +drop table if exists t_nvarchar2; +NOTICE: table "t_nvarchar2" does not exist, skipping +drop table if exists t_text; +create table t_nvarchar2(cont nvarchar2(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nvarchar2 select cont from t_text; +WARNING: value too long for type nvarchar2(6) +CONTEXT: referenced column: cont +WARNING: value too long for type nvarchar2(6) +CONTEXT: referenced column: cont +select * from t_nvarchar2; + cont +-------- + abcdef + abcdef + 123456 +(3 rows) + +-- test for nvarchar2 converting +drop table if exists t_nvarchar2; +drop table if exists t_text; +create table t_nvarchar2(cont nvarchar2); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nvarchar2 select cont from t_text; +select * from t_nvarchar2; + cont +-------------------- + abcdef + abcdefghj + 123456789123456789 +(3 rows) + +-- test for integer-string-mixed value in +drop table if exists t_int; +create table t_int(num int); +insert /*+ ignore_error */ into t_int values('12a34'); +select * from t_int; + num +----- + 12 +(1 row) + +\c postgres +drop database if exists sql_ignore_type_transform_test; diff --git a/src/test/regress/expected/ignore/ignore_unique_constraints.out b/src/test/regress/expected/ignore/ignore_unique_constraints.out new file mode 100644 index 000000000..108834456 --- /dev/null +++ b/src/test/regress/expected/ignore/ignore_unique_constraints.out @@ -0,0 +1,369 @@ +create database sql_ignore_unique_test dbcompatibility 'B'; +\c sql_ignore_unique_test; +drop table if exists t_ignore; +NOTICE: table "t_ignore" does not exist, skipping +create table t_ignore(col1 int, col2 int unique, col3 int unique); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_ignore_col2_key" for table "t_ignore" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_ignore_col3_key" for table "t_ignore" +-- sqlbypass +set enable_opfusion = on; +insert into t_ignore values(1,1,1); +insert into t_ignore values(2,2,2); +update t_ignore set col2 = 1 where col1 = 2; +ERROR: duplicate key value violates unique constraint "t_ignore_col2_key" +DETAIL: Key (col2)=(1) already exists. +insert /*+ ignore_error */ into t_ignore values (2,1,2); +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + col1 | col2 | col3 +------+------+------ + 1 | 1 | 1 + 2 | 2 | 2 +(2 rows) + +update /*+ ignore_error */ t_ignore set col2 = 1 where col1 = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + col1 | col2 | col3 +------+------+------ + 1 | 1 | 1 + 2 | 2 | 2 +(2 rows) + +-- insert ignore from other tables with duplicate keys +create table t_from (col1 int, col2 int, col3 int); +insert into t_from values(9,9,9); +insert into t_from values(1,1,1); +insert into t_from values(2,2,2); +insert into t_ignore select * from t_from; +ERROR: duplicate key value violates unique constraint "t_ignore_col2_key" +DETAIL: Key (col2)=(1) already exists. +select * from t_ignore; + col1 | col2 | col3 +------+------+------ + 1 | 1 | 1 + 2 | 2 | 2 +(2 rows) + +-- no sqlbypass +set enable_opfusion = off; +insert into t_ignore values(2,1,2); +ERROR: duplicate key value violates unique constraint "t_ignore_col2_key" +DETAIL: Key (col2)=(1) already exists. +update t_ignore set col2 = 1 where col1 = 2; +ERROR: duplicate key value violates unique constraint "t_ignore_col2_key" +DETAIL: Key (col2)=(1) already exists. +insert /*+ ignore_error */ into t_ignore values(2,1,2); +WARNING: duplicate key value violates unique constraint in table "t_ignore" +update /*+ ignore_error */ t_ignore set col2 = 1 where col1 = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + col1 | col2 | col3 +------+------+------ + 1 | 1 | 1 + 2 | 2 | 2 +(2 rows) + +-- insert ignore from other tables with duplicate keys +insert into t_ignore select * from t_from; +ERROR: duplicate key value violates unique constraint "t_ignore_col2_key" +DETAIL: Key (col2)=(1) already exists. +select * from t_ignore; + col1 | col2 | col3 +------+------+------ + 1 | 1 | 1 + 2 | 2 | 2 +(2 rows) + +drop table t_ignore; +set enable_opfusion = on; +drop table t_from; +-- test for integrity of UPSERT +drop table if exists t_unique_upsert; +NOTICE: table "t_unique_upsert" does not exist, skipping +create table t_unique_upsert(id int unique, cont text); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_unique_upsert_id_key" for table "t_unique_upsert" +set enable_opfusion = on; +insert into t_unique_upsert values(1, 'a'); +insert into t_unique_upsert values(2, 'b'); +insert /*+ ignore_error */ into t_unique_upsert values(1, 'x') on duplicate key update cont = 'on dup'; +select * from t_unique_upsert; + id | cont +----+-------- + 2 | b + 1 | on dup +(2 rows) + +delete from t_unique_upsert; +set enable_opfusion = off; +insert into t_unique_upsert values(1, 'a'); +insert into t_unique_upsert values(2, 'b'); +insert /*+ ignore_error */ into t_unique_upsert values(1, 'x') on duplicate key update cont = 'on dup'; +select * from t_unique_upsert; + id | cont +----+-------- + 2 | b + 1 | on dup +(2 rows) + +-- test for partition table with unique key +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_unique_key_partition; +NOTICE: table "t_unique_key_partition" does not exist, skipping +CREATE TABLE t_unique_key_partition +( + num integer UNIQUE NOT NULL, + ca_city character varying(60) +) PARTITION BY RANGE (num) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000), + PARTITION P4 VALUES LESS THAN(20000), + PARTITION P5 VALUES LESS THAN(25000), + PARTITION P6 VALUES LESS THAN(30000), + PARTITION P7 VALUES LESS THAN(40000) +); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_unique_key_partition_num_key" for table "t_unique_key_partition" +insert into t_unique_key_partition values(1, 'shenzhen'); +insert into t_unique_key_partition values(2, 'beijing'); +select * from t_unique_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 2 | beijing +(2 rows) + +explain(costs off) insert /*+ ignore_error */ into t_unique_key_partition values (1); + QUERY PLAN +---------------------------------- + [Bypass] + Insert on t_unique_key_partition + -> Result +(3 rows) + +insert /*+ ignore_error */ into t_unique_key_partition values (1); +WARNING: duplicate key value violates unique constraint in table "t_unique_key_partition" +select * from t_unique_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 2 | beijing +(2 rows) + +update /*+ ignore_error */ t_unique_key_partition set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_unique_key_partition" +select * from t_unique_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 2 | beijing +(2 rows) + +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; +explain(costs off) insert /*+ ignore_error */ into t_unique_key_partition values (1); + QUERY PLAN +---------------------------------- + Insert on t_unique_key_partition + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_unique_key_partition values (1); +WARNING: duplicate key value violates unique constraint in table "t_unique_key_partition" +select * from t_unique_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 2 | beijing +(2 rows) + +update /*+ ignore_error */ t_unique_key_partition set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_unique_key_partition" +select * from t_unique_key_partition; + num | ca_city +-----+---------- + 1 | shenzhen + 2 | beijing +(2 rows) + +-- test for subpartition table +drop table if exists ignore_range_range; +NOTICE: table "ignore_range_range" does not exist, skipping +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code VARCHAR2 ( 30 ) UNIQUE , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) + PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201901_b VALUES LESS THAN( '3' ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201902_b VALUES LESS THAN( '3' ) + ) +); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "ignore_range_range_dept_code_tableoid_key" for table "ignore_range_range" +set enable_opfusion = on; +set enable_partition_opfusion = on; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +WARNING: duplicate key value violates unique constraint in table "ignore_range_range" +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +insert into ignore_range_range values('201901', '2', '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = '1' where dept_code = '2'; +WARNING: duplicate key value violates unique constraint in table "ignore_range_range" +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 + 201901 | 2 | 1 | 1 +(2 rows) + +delete from ignore_range_range; +set enable_opfusion = off; +set enable_partition_opfusion = off; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +WARNING: duplicate key value violates unique constraint in table "ignore_range_range" +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 +(1 row) + +insert into ignore_range_range values('201901', '2', '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = '1' where dept_code = '2'; +WARNING: duplicate key value violates unique constraint in table "ignore_range_range" +select * from ignore_range_range; + month_code | dept_code | user_no | sales_amt +------------+-----------+---------+----------- + 201901 | 1 | 1 | 1 + 201901 | 2 | 1 | 1 +(2 rows) + +-- test for ustore table +drop table if exists t_ignore; +NOTICE: table "t_ignore" does not exist, skipping +create table t_ignore(num int unique) with(storage_type=ustore); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_ignore_num_key" for table "t_ignore" +-- test for ustore table, opfusion: on +set enable_opfusion = on; +insert into t_ignore values(1); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1); + QUERY PLAN +-------------------- + [Bypass] + Insert on t_ignore + -> Result +(3 rows) + +select * from t_ignore; + num +----- + 1 +(1 row) + +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 + 2 +(2 rows) + +-- test for ustore table, opfusion: off +set enable_opfusion = off; +delete from t_ignore; +insert into t_ignore values(1); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1); + QUERY PLAN +-------------------- + Insert on t_ignore + -> Result +(2 rows) + +insert /*+ ignore_error */ into t_ignore values(1); +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 +(1 row) + +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 + 2 +(2 rows) + +-- test for segment table +drop table if exists t_ignore; +create table t_ignore(num int unique) with(segment = on); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_ignore_num_key" for table "t_ignore" +-- test for segment table, opfusion: on +set enable_opfusion = on; +insert into t_ignore values(1); +insert /*+ ignore_error */ into t_ignore values(1); +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 +(1 row) + +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 + 2 +(2 rows) + +-- test for segment table, opfusion: off +delete from t_ignore; +set enable_opfusion = off; +insert into t_ignore values(1); +insert /*+ ignore_error */ into t_ignore values(1); +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 +(1 row) + +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +WARNING: duplicate key value violates unique constraint in table "t_ignore" +select * from t_ignore; + num +----- + 1 + 2 +(2 rows) + +\c postgres +drop database if exists sql_ignore_unique_test; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index d67cf9db3..7b77200a5 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -919,3 +919,4 @@ test: gs_dump_encrypt test: composite_datum_record mysql_function test: join_test_alias +test: ignore/ignore_type_transform ignore/ignore_not_null_constraints ignore/ignore_unique_constraints ignore/ignore_no_matched_partition \ No newline at end of file diff --git a/src/test/regress/sql/ignore/ignore_no_matched_partition.sql b/src/test/regress/sql/ignore/ignore_no_matched_partition.sql new file mode 100644 index 000000000..0e436bee5 --- /dev/null +++ b/src/test/regress/sql/ignore/ignore_no_matched_partition.sql @@ -0,0 +1,161 @@ +-- test for ignore error of no partition matched +create database sql_ignore_no_matched_partition_test dbcompatibility 'B'; +\c sql_ignore_no_matched_partition_test; + +-- sqlbypass +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_ignore; +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; +insert into t_ignore values(20000, 'abc'); +insert into t_ignore values(3000, 'abc'); +update t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; + +drop table if exists t_from; +create table t_from (num int, content character varying(60)); +-- -- insert ignore from other tables with unmatchable rows +insert into t_from values(1000, 'valid row from t_from'); +insert into t_from values(20000, 'INVALID row from t_from'); +insert /*+ ignore_error */ into t_ignore select * from t_from; +select * from t_ignore; + +-- no sqlbypass +set enable_opfusion = off; +set enable_partition_opfusion = off; +insert into t_ignore values(1000, 'abc'); +insert into t_ignore values(30000, 'abc'); +update t_ignore set col1 = 30000 where col1 = 1000; +select * from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(30000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(30000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 30000 where col1 = 1000; +select * from t_ignore; + +-- insert ignore from other tables with unmatchable rows +insert /*+ ignore_error */ into t_ignore select * from t_from; +select * from t_ignore; + +-- test for subpartition table +drop table if exists ignore_range_range; +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code VARCHAR2 ( 30 ) NOT NULL , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) +PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201901_b VALUES LESS THAN( '3' ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201902_b VALUES LESS THAN( '3' ) + ) +); +set enable_partition_opfusion = on; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '4', '1', 1); +select * from ignore_range_range; +update /*+ ignore_error */ ignore_range_range set dept_code = '4' where dept_code = '1'; +select * from ignore_range_range; +delete from ignore_range_range; +set enable_partition_opfusion = off; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '4', '1', 1); +select * from ignore_range_range; +update /*+ ignore_error */ ignore_range_range set dept_code = '4' where dept_code = '1'; +select * from ignore_range_range; + +-- test for ustore table +drop table if exists t_ignore; +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) WITH(storage_type=ustore) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; +-- test for ustore table, opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +explain (costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +select * from t_ignore; +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; + +-- test for ustore table, opfusion: off +delete from t_ignore; +set enable_opfusion = off; +set enable_partition_opfusion = off; +explain (costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +select * from t_ignore; +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; + +-- test for segment table +drop table if exists t_ignore; +CREATE TABLE t_ignore +( + col1 integer NOT NULL, + col2 character varying(60) +) WITH(segment = on) PARTITION BY RANGE (col1) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000) +) +ENABLE ROW MOVEMENT; + +-- test for segment table, opfusion: on +set enable_partition_opfusion = on; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +select * from t_ignore; +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; + +-- test for segment table, opfusion: off +set enable_partition_opfusion = off; +delete from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +insert /*+ ignore_error */ into t_ignore values(20000, 'abc'); +select * from t_ignore; +insert into t_ignore values(3000, 'abc'); +update /*+ ignore_error */ t_ignore set col1 = 20000 where col1 = 3000; +select * from t_ignore; + +set enable_opfusion = on; +set enable_partition_opfusion = off; +drop table t_ignore; +drop table t_from; +\c postgres +drop database if exists sql_ignore_no_matched_partition_test; \ No newline at end of file diff --git a/src/test/regress/sql/ignore/ignore_not_null_constraints.sql b/src/test/regress/sql/ignore/ignore_not_null_constraints.sql new file mode 100644 index 000000000..eda95aaa3 --- /dev/null +++ b/src/test/regress/sql/ignore/ignore_not_null_constraints.sql @@ -0,0 +1,546 @@ +-- test for insert/update ignore. +create database sql_ignore_not_null_test dbcompatibility 'B'; +\c sql_ignore_not_null_test; +drop table if exists t_ignore; +create table t_ignore(col1 int, col2 int not null, col3 varchar not null); + +-- sqlbypass +set enable_opfusion = on; +-- test for condition without ignore +insert into t_ignore values(1, 1, 'abcdef'); +insert into t_ignore values(1, null, null); +insert into t_ignore values(1, null, 'abcdef'); +insert into t_ignore values(1, 1, null); +insert into t_ignore values(1, null, null); +select * from t_ignore; +update t_ignore set col2 = null, col3 = null; +select * from t_ignore; +-- test for condition with ignore +insert /*+ ignore_error */ into t_ignore values(1, 1, 'abcdef'); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, 'abcdef'); +insert /*+ ignore_error */ into t_ignore values(1, 1, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +select * from t_ignore; +update /*+ ignore_error */ t_ignore set col2 = null, col3 = null; +select * from t_ignore; + +-- insert ignore from other tables with null +drop table if exists t_from; +create table t_from (col1 int, col2 int, col3 varchar); +insert into t_from values(9,9,'row from others'); +insert into t_from values(1, null, null); +insert /*+ ignore_error */ into t_ignore select * from t_from; +select * from t_ignore; + +-- test for null replacement +set sql_ignore_strategy = 'overwrite_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +select * from t_ignore; +set sql_ignore_strategy = 'ignore_null'; + +-- no bypass +set enable_opfusion = off; +-- test for condition without ignore +insert into t_ignore values(1, 1, 'abcdef'); +insert into t_ignore values(1, null, null); +insert into t_ignore values(1, null, 'abcdef'); +insert into t_ignore values(1, 1, null); +insert into t_ignore values(1, null, null); +select * from t_ignore; +update t_ignore set col2 = null, col3 = null; +select * from t_ignore; +-- test for condition with ignore +insert /*+ ignore_error */ into t_ignore values(1, 1, 'abcdef'); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, 'abcdef'); +insert /*+ ignore_error */ into t_ignore values(1, 1, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +select * from t_ignore; +update t_ignore set col2 = null, col3 = null; +select * from t_ignore; + +-- insert ignore from other tables with null +insert /*+ ignore_error */ into t_ignore select * from t_from; +select * from t_ignore; + +-- test for null replacement +set sql_ignore_strategy = 'overwrite_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1, null, null); +insert /*+ ignore_error */ into t_ignore values(1, null, null); +select * from t_ignore; +set sql_ignore_strategy = 'ignore_null'; + +-- test for overwriting null into "zero" of specific type +set sql_ignore_strategy = 'overwrite_null'; + +-- timestamp +create table t_timestamp(c timestamp not null); +insert /*+ ignore_error */ into t_timestamp values (null); +select * from t_timestamp; +insert into t_timestamp values('2022-06-01 17:26:59.846448'); +update /*+ ignore_error */ t_timestamp set c = null; +select * from t_timestamp; + +-- timetz +create table t_timetz(c timetz not null); +insert /*+ ignore_error */ into t_timetz values (null); +select * from t_timetz; +insert into t_timetz values('00:00:01+08'); +update /*+ ignore_error */ t_timetz set c = null; +select * from t_timetz; + +-- time +create table t_time(c time not null); +insert /*+ ignore_error */ into t_time values (null); +select * from t_time; +insert into t_time values('00:00:00'); +update /*+ ignore_error */ t_time set c = null; +select * from t_time; + +-- interval +create table t_interval(c interval not null); +insert /*+ ignore_error */ into t_interval values (null); +select * from t_interval; +insert into t_interval values('00:00:01'); +update /*+ ignore_error */ t_interval set c = null; +select * from t_interval; + +-- tinterval +create table t_tinterval(c tinterval not null); +insert /*+ ignore_error */ into t_tinterval values (null); +select * from t_tinterval; +update /*+ ignore_error */ t_tinterval set c = null; +select * from t_tinterval; + +-- smalldatetime +create table t_smalldatetime(c smalldatetime not null); +insert /*+ ignore_error */ into t_smalldatetime values (null); +select * from t_smalldatetime; +insert into t_smalldatetime values('1991-01-01 08:00:00'); +update /*+ ignore_error */ t_smalldatetime set c = null; +select * from t_smalldatetime; + +-- date +create table t_date(c date not null); +insert /*+ ignore_error */ into t_date values (null); +select * from t_date; +insert into t_date values('1991-01-01 08:00:00'); +update /*+ ignore_error */ t_date set c = null; +select * from t_date; + +-- uuid +create table t_uuid(c uuid not null); +insert /*+ ignore_error */ into t_uuid values (null); +select * from t_uuid; +insert into t_uuid values('aaaaaaaa-0000-0000-0000-000000000000'); +update /*+ ignore_error */ t_uuid set c = null; +select * from t_uuid; + +-- name +create table t_name(c name not null); +insert /*+ ignore_error */ into t_name values (null); +select * from t_name; +insert into t_name values('abc'); +update /*+ ignore_error */ t_name set c = null; +select * from t_name; + +-- point +create table t_point(c point not null); +insert /*+ ignore_error */ into t_point values (null); +select * from t_point; +insert into t_point values('(1,1)'); +update /*+ ignore_error */ t_point set c = null; +select * from t_point; + +-- path +create table t_path(c path not null); +insert /*+ ignore_error */ into t_path values (null); +select * from t_path; +insert into t_path values('((1,1))'); +update /*+ ignore_error */ t_path set c = null; +select * from t_path; + +-- polygon +create table t_polygon(c polygon not null); +insert /*+ ignore_error */ into t_polygon values (null); +select * from t_polygon; +insert into t_polygon values('((1,1))'); +update /*+ ignore_error */ t_polygon set c = null; +select * from t_polygon; + +-- circle +create table t_circle(c circle not null); +insert /*+ ignore_error */ into t_circle values (null); +select * from t_circle; +insert into t_circle values('<(1,1),1>'); +update /*+ ignore_error */ t_circle set c = null; +select * from t_circle; + +-- box +create table t_box(c box not null); +insert /*+ ignore_error */ into t_box values (null); +select * from t_box; +insert into t_box values('(1,1),(2,2)'); +update /*+ ignore_error */ t_box set c = null; +select * from t_box; + +-- json +create table t_json(c json not null); +insert /*+ ignore_error */ into t_json values (null); +select * from t_json; +insert into t_json values('111'); +update /*+ ignore_error */ t_json set c = null; +select * from t_json; + +-- jsonb +create table t_jsonb(c jsonb not null); +insert /*+ ignore_error */ into t_jsonb values (null); +select * from t_jsonb; +insert into t_jsonb values('111'); +update /*+ ignore_error */ t_jsonb set c = null; +select * from t_jsonb; + +-- bit +create table t_bit(c bit not null); +insert /*+ ignore_error */ into t_bit values (null); +select * from t_bit; +insert into t_bit values('1'); +update /*+ ignore_error */ t_bit set c = null; +select * from t_bit; + +-- tinyint +create table t_tinyint(c tinyint not null); +insert /*+ ignore_error */ into t_tinyint values (null); +select * from t_tinyint; +insert into t_tinyint values('10'); +update /*+ ignore_error */ t_tinyint set c = null; +select * from t_tinyint; + +-- smallint +create table t_smallint(c smallint not null); +insert /*+ ignore_error */ into t_smallint values (null); +select * from t_smallint; +insert into t_smallint values('123'); +update /*+ ignore_error */ t_smallint set c = null; +select * from t_smallint; + + +-- int +create table t_int(c int not null); +insert /*+ ignore_error */ into t_int values (null); +select * from t_int; +insert into t_int values(9999); +update /*+ ignore_error */ t_int set c = null; +select * from t_int; + +-- bigint +create table t_bigint(c bigint not null); +insert /*+ ignore_error */ into t_bigint values (null); +select * from t_bigint; +insert into t_bigint values(9999999999999999); +update /*+ ignore_error */ t_bigint set c = null; +select * from t_bigint; + +-- float +create table t_float(c float not null); +insert /*+ ignore_error */ into t_float values (null); +select * from t_float; +insert into t_float values(123.99); +update /*+ ignore_error */ t_float set c = null; +select * from t_float; + +-- float8 +create table t_float8(c float8 not null); +insert /*+ ignore_error */ into t_float8 values (null); +select * from t_float8; +insert into t_float8 values(123.99); +update /*+ ignore_error */ t_float8 set c = null; +select * from t_float8; + +-- numeric +create table t_numeric(c numeric not null); +insert /*+ ignore_error */ into t_numeric values (null); +select * from t_numeric; +insert into t_numeric values(123.99); +update /*+ ignore_error */ t_numeric set c = null; +select * from t_numeric; + +-- serial +create table t_serial(c serial not null); +insert /*+ ignore_error */ into t_serial values (null); +select * from t_serial; +insert into t_serial values(123); +update /*+ ignore_error */ t_serial set c = null; +select * from t_serial; + +-- bool +create table t_bool(c bool not null); +insert /*+ ignore_error */ into t_bool values (null); +select * from t_bool; +insert into t_bool values(true); +update /*+ ignore_error */ t_bool set c = null; +select * from t_bool; + +-- char(n) +create table t_charn(c char(6) not null); +insert /*+ ignore_error */ into t_charn values (null); +select * from t_charn; +insert into t_charn values('abc'); +update /*+ ignore_error */ t_charn set c = null; +select * from t_charn; + +-- varchar(n) +create table t_varcharn(c varchar(6) not null); +insert /*+ ignore_error */ into t_varcharn values (null); +select * from t_varcharn; +insert into t_varcharn values('xxxxxx'); +update /*+ ignore_error */ t_varcharn set c = null; +select * from t_varcharn; + +-- text +create table t_text(c text not null); +insert /*+ ignore_error */ into t_text values (null); +select * from t_text; +insert into t_text values('xxxxxx'); +update /*+ ignore_error */ t_text set c = null; +select * from t_text; + +-- mixture +drop table if exists t_mix; +create table t_mix +( + c1 int, + c2 bigint not null, + c3 varchar(6) not null, + c4 bool not null +); +insert /*+ ignore_error */ into t_mix values(1, null, null, null); +insert /*+ ignore_error */ into t_mix values(2, 2, null, null); +select * from t_mix; +insert into t_mix values(2, 2, 'abced', true); +update /*+ ignore_error */ t_mix set c1 = 9, c2 = null, c3 = null, c4 = null; +select * from t_mix; +drop table if exists t_mix; + +-- test for mixture of not null constraints and check constraints +create table t_mix(num int not null check(num > 5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +drop table if exists t_mix; + +create table t_mix(num int not null check(num > -5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +drop table if exists t_mix; + +create table t_mix(content text not null check(length(content) > 5)); +set sql_ignore_strategy = 'overwrite_null'; +set enable_opfusion = on; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +set enable_opfusion = off; +insert /*+ ignore_error */ into t_mix values(null); +select * from t_mix; +drop table if exists t_mix; + +-- test for partition table with not null constraint +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_not_null_key_partition; +CREATE TABLE t_not_null_key_partition +( + num integer NOT NULL, + ca_city character varying(60) +) PARTITION BY RANGE (num) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000), + PARTITION P4 VALUES LESS THAN(20000), + PARTITION P5 VALUES LESS THAN(25000), + PARTITION P6 VALUES LESS THAN(30000), + PARTITION P7 VALUES LESS THAN(40000) +); +insert into t_not_null_key_partition values(1, 'shenzhen'); +select * from t_not_null_key_partition; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_not_null_key_partition values (null); +insert /*+ ignore_error */ into t_not_null_key_partition values (null); +select * from t_not_null_key_partition; +update /*+ ignore_error */ t_not_null_key_partition set num = null; +select * from t_not_null_key_partition; +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_not_null_key_partition values (null); +select * from t_not_null_key_partition; +update /*+ ignore_error */ t_not_null_key_partition set num = null; +select * from t_not_null_key_partition; + +-- test for subpartition table +drop table if exists ignore_range_range; +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code int NOT NULL , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) + PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( -5 ), + SUBPARTITION p_201901_b VALUES LESS THAN( 1 ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( -5 ), + SUBPARTITION p_201902_b VALUES LESS THAN( 1 ) + ) +); +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; + +-- sql_ignore_strategy: ignore_null +set sql_ignore_strategy = 'ignore_null'; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +select * from ignore_range_range; + +-- sql_ignore_strategy: overwrite_null +delete from ignore_range_range; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +select * from ignore_range_range; + +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; + +-- sql_ignore_strategy: ignore_null +set sql_ignore_strategy = 'ignore_null'; +delete from ignore_range_range; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +select * from ignore_range_range; + +-- sql_ignore_strategy: overwrite_null +set sql_ignore_strategy = 'overwrite_null'; +delete from ignore_range_range; +insert /*+ ignore_error */ into ignore_range_range values('201901', null, '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', -3, '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = null where dept_code = -3; +select * from ignore_range_range; +delete from ignore_range_range; + +-- test for ustore table +drop table if exists t_ignore; +create table t_ignore(num int not null) with (storage_type = ustore); + +-- opfusion: on +set enable_opfusion = on; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +delete from t_ignore; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +-- opfusion: off +delete from t_ignore; +set enable_opfusion = off; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +delete from t_ignore; +set sql_ignore_strategy = 'overwrite_null'; +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +-- test for segment table +drop table if exists t_ignore; +create table t_ignore(num int not null) with (segment = on); + +-- test for segment table, opfusion: on +set enable_opfusion = on; +set sql_ignore_strategy = 'ignore_null'; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +set sql_ignore_strategy = 'overwrite_null'; +delete from t_ignore; +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +-- test for segment table, opfusion: off +set enable_opfusion = off; +set sql_ignore_strategy = 'ignore_null'; +delete from t_ignore; +explain(costs off) insert /*+ ignore_error */ into t_ignore values(null); +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +set sql_ignore_strategy = 'overwrite_null'; +delete from t_ignore; +insert /*+ ignore_error */ into t_ignore values(null); +select * from t_ignore; +insert into t_ignore values(1); +update /*+ ignore_error */ t_ignore set num = null where num = 1; +select * from t_ignore; + +-- restore context +\c postgres +drop database if exists sql_ignore_not_null_test; \ No newline at end of file diff --git a/src/test/regress/sql/ignore/ignore_type_transform.sql b/src/test/regress/sql/ignore/ignore_type_transform.sql new file mode 100644 index 000000000..118ccb372 --- /dev/null +++ b/src/test/regress/sql/ignore/ignore_type_transform.sql @@ -0,0 +1,346 @@ +create database sql_ignore_type_transform_test dbcompatibility 'B'; +\c sql_ignore_type_transform_test; + +-- test for tinyint +drop table if exists t; +create table t(num tinyint); +insert into t values(10000); +insert into t values(-10000); +insert into t values(100); +insert into t values(-100); +insert /*+ ignore_error */ into t values(10000); +insert /*+ ignore_error */ into t values(-10000); +insert /*+ ignore_error */ into t values(100); +insert /*+ ignore_error */ into t values(-100); +select * from t; +update /*+ ignore_error */ t set num = 100000 where num = 100; +select * from t; + +-- insert numeric table into tinyint table +drop table if exists t_tinyint; +drop table if exists t_numeric; +create table t_tinyint(num tinyint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_tinyint select num from t_numeric; +select * from t_tinyint; + +-- test for smallint +drop table if exists t; +create table t(num smallint); +insert into t values(100000); +insert into t values(-100000); +insert into t values(10000); +insert into t values(-10000); +insert /*+ ignore_error */ into t values(100000); +insert /*+ ignore_error */ into t values(-100000); +insert /*+ ignore_error */ into t values(10000); +insert /*+ ignore_error */ into t values(-10000); +select * from t; +update /*+ ignore_error */ t set num = 1000000 where num = 10000; +select * from t; + +-- insert numeric table into smallint table +drop table if exists t_smallint; +drop table if exists t_numeric; +create table t_smallint(num smallint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_smallint select num from t_numeric; +select * from t_smallint; + +-- test for int +drop table if exists t; +create table t(num int); +insert into t values(10000000000); +insert into t values(-10000000000); +insert into t values(1000000); +insert into t values(-1000000); +insert /*+ ignore_error */ into t values(10000000000); +insert /*+ ignore_error */ into t values(-10000000000); +insert /*+ ignore_error */ into t values(1000000); +insert /*+ ignore_error */ into t values(-1000000); +select * from t; +update /*+ ignore_error */ t set num = 99999999999999999999 where num = 1000000; +select * from t; + +-- insert numeric table into int table +drop table if exists t_int; +drop table if exists t_numeric; +create table t_int(num int); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_int select num from t_numeric; +select * from t_int; + +-- test for bigint +drop table if exists t; +create table t(num bigint); +insert into t values(847329847839274398574389574398579834759384504385094386073456058984); +insert into t values(-439058439498375898437567893745893275984375984375984375984345498759438); +insert into t values(10000000::numeric); +insert into t values(-10000000::numeric); +insert /*+ ignore_error */ into t values(847329847839274398574389574398579834759384504385094386073456058984); +insert /*+ ignore_error */ into t values(-439058439498375898437567893745893275984375984375984375984345498759438); +insert /*+ ignore_error */ into t values(10000000::numeric); +insert /*+ ignore_error */ into t values(-10000000::numeric); +select * from t; +update /*+ ignore_error */ t set num = 99999999999999999999999999999999999999999999999999999999999999999999999999 where num = 10000000; +select * from t; + +-- insert numeric table into bigint table +drop table if exists t_bigint; +drop table if exists t_numeric; +create table t_bigint(num bigint); +create table t_numeric(num numeric); +insert into t_numeric values (38764378634891278678324089237898634298778923472389687.123874); +insert into t_numeric values (-38764378634891278678324089237898634298778923472389687.123874); +insert /*+ ignore_error */ into t_bigint select num from t_numeric; +select * from t_bigint; + +-- insert int table into tinyint table +drop table if exists t_int; +drop table if exists t_tinyint; +create table t_int(num int); +create table t_tinyint(num tinyint); +insert into t_int values(10000); +insert into t_int values(-10000); +insert /*+ ignore_error */ into t_tinyint select num from t_int; +select * from t_tinyint; + +-- insert int table into smallint table +drop table if exists t_int; +drop table if exists t_smallint; +create table t_int(num int); +create table t_smallint(num smallint); +insert into t_int values(1000000); +insert into t_int values(-1000000); +insert /*+ ignore_error */ into t_smallint select num from t_int; +select * from t_smallint; + +-- test for float4 to tinyint +drop table if exists t_tinyint; +create table t_tinyint(num tinyint); +insert into t_tinyint values (10000.023::float4); +insert into t_tinyint values (-10000.023::float4); +insert into t_tinyint values (123.023::float4); +insert into t_tinyint values (-123.023::float4); +insert /*+ ignore_error */ into t_tinyint values (10000.023::float4); +insert /*+ ignore_error */ into t_tinyint values (-10000.023::float4); +insert /*+ ignore_error */ into t_tinyint values (123.023::float4); +insert /*+ ignore_error */ into t_tinyint values (-123.023::float4); +select * from t_tinyint; + +-- test for float4 to smallint +drop table if exists t_smallint; +create table t_smallint(num smallint); +insert into t_smallint values (1000000.023::float4); +insert into t_smallint values (-1000000.023::float4); +insert into t_smallint values (10000.023::float4); +insert into t_smallint values (-10000.023::float4); +insert /*+ ignore_error */ into t_smallint values (1000000.023::float4); +insert /*+ ignore_error */ into t_smallint values (-1000000.023::float4); +insert /*+ ignore_error */ into t_smallint values (10000.023::float4); +insert /*+ ignore_error */ into t_smallint values (-10000.023::float4); +select * from t_smallint; + +-- test for float4 to int +drop table if exists t_int; +create table t_int(num int); +insert into t_int values (72348787598743985743895.023::float4); +insert into t_int values (-72348787598743985743895.023::float4); +insert into t_int values (123123.023::float4); +insert into t_int values (-123123.023::float4); +insert /*+ ignore_error */ into t_int values (72348787598743985743895.023::float4); +insert /*+ ignore_error */ into t_int values (-72348787598743985743895.023::float4); +insert /*+ ignore_error */ into t_int values (123123.023::float4); +insert /*+ ignore_error */ into t_int values (-123123.023::float4); +select * from t_int; + +-- test for float4 to bigint +drop table if exists t_bigint; +create table t_bigint(num bigint); +insert into t_bigint values (238947289573489758943455436587549686.023::float4); +insert into t_bigint values (-238947289573489758943455436587549686.023::float4); +insert into t_bigint values (100000.023::float4); +insert into t_bigint values (-100000.023::float4); +insert /*+ ignore_error */ into t_bigint values (238947289573489758943455436587549686.023::float4); +insert /*+ ignore_error */ into t_bigint values (-238947289573489758943455436587549686.023::float4); +insert /*+ ignore_error */ into t_bigint values (100000.023::float4); +insert /*+ ignore_error */ into t_bigint values (-100000.023::float4); +select * from t_bigint; + +-- test for float8 to tinyint +drop table if exists t_tinyint; +create table t_tinyint(num tinyint); +insert into t_tinyint values (238947289573489758943455436587549686.023::float8); +insert into t_tinyint values (-238947289573489758943455436587549686.023::float8); +insert into t_tinyint values (100.123::float8); +insert into t_tinyint values (-100.123::float8); +insert /*+ ignore_error */ into t_tinyint values (238947289573489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_tinyint values (-238947289573489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_tinyint values (100.123::float8); +insert /*+ ignore_error */ into t_tinyint values (-100.123::float8); +select * from t_tinyint; + +-- test for float8 to smallint +drop table if exists t_smallint; +create table t_smallint(num smallint); +insert into t_smallint values (238947289573489758943455436587549686.023::float8); +insert into t_smallint values (-238947289573489758943455436587549686.023::float8); +insert into t_smallint values (100.023::float8); +insert into t_smallint values (-100.023::float8); +insert /*+ ignore_error */ into t_smallint values (238947289573489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_smallint values (-238947289573489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_smallint values (100.023::float8); +insert /*+ ignore_error */ into t_smallint values (-100.023::float8); +select * from t_smallint; + +-- test for float8 to int +drop table if exists t_int; +create table t_int(num int); +insert into t_int values (23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +insert into t_int values (-23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +insert into t_int values (123.023::float8); +insert into t_int values (-123.023::float8); +insert /*+ ignore_error */ into t_int values (23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_int values (-23894728957345798437986755479865476509486804965449876953489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_int values (123.023::float8); +insert /*+ ignore_error */ into t_int values (-123.023::float8); +select * from t_int; + +-- test for float8 to bigint +drop table if exists t_bigint; +create table t_bigint(num bigint); +insert into t_bigint values (238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +insert into t_bigint values (-238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +insert into t_bigint values (123.123::float8); +insert into t_bigint values (-123.123::float8); +insert /*+ ignore_error */ into t_bigint values (238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_bigint values (-238947289573457984379867554798658438574983768504985454690874578759765898798798709854353476509486804965449876953489758943455436587549686.023::float8); +insert /*+ ignore_error */ into t_bigint values (123.123::float8); +insert /*+ ignore_error */ into t_bigint values (-123.123::float8); +select * from t_bigint; + +-- test for float8 to float4 +drop table if exists t_float4; +create table t_float4(num float4); +insert into t_float4 values (1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +insert into t_float4 values (-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +insert into t_float4 values(123.123::float8); +insert into t_float4 values(-123.123::float8); +insert /*+ ignore_error */ into t_float4 values (1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +insert /*+ ignore_error */ into t_float4 values (-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984::float8); +insert /*+ ignore_error */ into t_float4 values(123.123::float8); +insert /*+ ignore_error */ into t_float4 values(-123.123::float8); +select * from t_float4; + +-- test for numeric to float4 +drop table if exists t_numeric; +drop table if exists t_float4; +create table t_numeric(num numeric); +create table t_float4(num float4); +insert into t_numeric values(1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984); +insert into t_numeric values(-1892038097432987589432759843769348605436304758493758943758943758943759843756983760945860948605948765487689547893475893475918920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759627346378267863475863875648365843734895749837589437589473988.18920380974329875894327598437693486054363047584937589437589437589437598437569837609458609486059487654876895478934758934759189203809743298758943275984376934860543630475849375894375894375894375984375698376094586094860594876548768954789347589347593874894375984); +insert /*+ ignore_error */ into t_float4 select num from t_numeric; +select * from t_float4; + +-- test for char(n) converting +drop table if exists t_char; +drop table if exists t_text; +create table t_char(cont char(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_char select cont from t_text; +select * from t_char; + +-- test for varchar(n) converting +drop table if exists t_varchar; +drop table if exists t_text; +create table t_varchar(cont varchar(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_varchar select cont from t_text; +select * from t_varchar; + +-- test for character(n) converting +drop table if exists t_character; +drop table if exists t_text; +create table t_character(cont character(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_character select cont from t_text; +select * from t_character; + +-- test for nchar(n) converting +drop table if exists t_nchar; +drop table if exists t_text; +create table t_nchar(cont nchar(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nchar select cont from t_text; +select * from t_nchar; + +-- test for character converting +drop table if exists t_character; +drop table if exists t_text; +create table t_character(cont character); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_character select cont from t_text; +select * from t_character; + +-- test for varchar2(n) converting +drop table if exists t_varchar2; +drop table if exists t_text; +create table t_varchar2(cont varchar2(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_varchar2 select cont from t_text; +select * from t_varchar2; + +-- test for nvarchar2(n) converting +drop table if exists t_nvarchar2; +drop table if exists t_text; +create table t_nvarchar2(cont nvarchar2(6)); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nvarchar2 select cont from t_text; +select * from t_nvarchar2; + +-- test for nvarchar2 converting +drop table if exists t_nvarchar2; +drop table if exists t_text; +create table t_nvarchar2(cont nvarchar2); +create table t_text(cont text); +insert into t_text values('abcdef'); +insert into t_text values('abcdefghj'); +insert into t_text values(123456789123456789); +insert /*+ ignore_error */ into t_nvarchar2 select cont from t_text; +select * from t_nvarchar2; + +-- test for integer-string-mixed value in +drop table if exists t_int; +create table t_int(num int); +insert /*+ ignore_error */ into t_int values('12a34'); +select * from t_int; + +\c postgres +drop database if exists sql_ignore_type_transform_test; \ No newline at end of file diff --git a/src/test/regress/sql/ignore/ignore_unique_constraints.sql b/src/test/regress/sql/ignore/ignore_unique_constraints.sql new file mode 100644 index 000000000..e2e929f60 --- /dev/null +++ b/src/test/regress/sql/ignore/ignore_unique_constraints.sql @@ -0,0 +1,181 @@ +create database sql_ignore_unique_test dbcompatibility 'B'; +\c sql_ignore_unique_test; +drop table if exists t_ignore; +create table t_ignore(col1 int, col2 int unique, col3 int unique); + +-- sqlbypass +set enable_opfusion = on; +insert into t_ignore values(1,1,1); +insert into t_ignore values(2,2,2); +update t_ignore set col2 = 1 where col1 = 2; +insert /*+ ignore_error */ into t_ignore values (2,1,2); +select * from t_ignore; +update /*+ ignore_error */ t_ignore set col2 = 1 where col1 = 2; +select * from t_ignore; + +-- insert ignore from other tables with duplicate keys +create table t_from (col1 int, col2 int, col3 int); +insert into t_from values(9,9,9); +insert into t_from values(1,1,1); +insert into t_from values(2,2,2); +insert into t_ignore select * from t_from; +select * from t_ignore; + +-- no sqlbypass +set enable_opfusion = off; +insert into t_ignore values(2,1,2); +update t_ignore set col2 = 1 where col1 = 2; +insert /*+ ignore_error */ into t_ignore values(2,1,2); +update /*+ ignore_error */ t_ignore set col2 = 1 where col1 = 2; +select * from t_ignore; + +-- insert ignore from other tables with duplicate keys +insert into t_ignore select * from t_from; +select * from t_ignore; + +drop table t_ignore; +set enable_opfusion = on; +drop table t_from; + +-- test for integrity of UPSERT +drop table if exists t_unique_upsert; +create table t_unique_upsert(id int unique, cont text); +set enable_opfusion = on; +insert into t_unique_upsert values(1, 'a'); +insert into t_unique_upsert values(2, 'b'); +insert /*+ ignore_error */ into t_unique_upsert values(1, 'x') on duplicate key update cont = 'on dup'; +select * from t_unique_upsert; + +delete from t_unique_upsert; +set enable_opfusion = off; +insert into t_unique_upsert values(1, 'a'); +insert into t_unique_upsert values(2, 'b'); +insert /*+ ignore_error */ into t_unique_upsert values(1, 'x') on duplicate key update cont = 'on dup'; +select * from t_unique_upsert; + +-- test for partition table with unique key +-- opfusion: on +set enable_opfusion = on; +set enable_partition_opfusion = on; +drop table if exists t_unique_key_partition; +CREATE TABLE t_unique_key_partition +( + num integer UNIQUE NOT NULL, + ca_city character varying(60) +) PARTITION BY RANGE (num) +( + PARTITION P1 VALUES LESS THAN(5000), + PARTITION P2 VALUES LESS THAN(10000), + PARTITION P3 VALUES LESS THAN(15000), + PARTITION P4 VALUES LESS THAN(20000), + PARTITION P5 VALUES LESS THAN(25000), + PARTITION P6 VALUES LESS THAN(30000), + PARTITION P7 VALUES LESS THAN(40000) +); +insert into t_unique_key_partition values(1, 'shenzhen'); +insert into t_unique_key_partition values(2, 'beijing'); +select * from t_unique_key_partition; +explain(costs off) insert /*+ ignore_error */ into t_unique_key_partition values (1); +insert /*+ ignore_error */ into t_unique_key_partition values (1); +select * from t_unique_key_partition; +update /*+ ignore_error */ t_unique_key_partition set num = 1 where num = 2; +select * from t_unique_key_partition; +-- opfusion: off +set enable_opfusion = off; +set enable_partition_opfusion = off; +explain(costs off) insert /*+ ignore_error */ into t_unique_key_partition values (1); +insert /*+ ignore_error */ into t_unique_key_partition values (1); +select * from t_unique_key_partition; +update /*+ ignore_error */ t_unique_key_partition set num = 1 where num = 2; +select * from t_unique_key_partition; + +-- test for subpartition table +drop table if exists ignore_range_range; +CREATE TABLE ignore_range_range +( + month_code VARCHAR2 ( 30 ) NOT NULL , + dept_code VARCHAR2 ( 30 ) UNIQUE , + user_no VARCHAR2 ( 30 ) NOT NULL , + sales_amt int +) + PARTITION BY RANGE (month_code) SUBPARTITION BY RANGE (dept_code) +( + PARTITION p_201901 VALUES LESS THAN( '201901' ) + ( + SUBPARTITION p_201901_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201901_b VALUES LESS THAN( '3' ) + ), + PARTITION p_201902 VALUES LESS THAN( '201902' ) + ( + SUBPARTITION p_201902_a VALUES LESS THAN( '2' ), + SUBPARTITION p_201902_b VALUES LESS THAN( '3' ) + ) +); +set enable_opfusion = on; +set enable_partition_opfusion = on; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', '2', '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = '1' where dept_code = '2'; +select * from ignore_range_range; + +delete from ignore_range_range; +set enable_opfusion = off; +set enable_partition_opfusion = off; +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +insert /*+ ignore_error */ into ignore_range_range values('201901', '1', '1', 1); +select * from ignore_range_range; +insert into ignore_range_range values('201901', '2', '1', 1); +update /*+ ignore_error */ ignore_range_range set dept_code = '1' where dept_code = '2'; +select * from ignore_range_range; + +-- test for ustore table +drop table if exists t_ignore; +create table t_ignore(num int unique) with(storage_type=ustore); + +-- test for ustore table, opfusion: on +set enable_opfusion = on; +insert into t_ignore values(1); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1); +select * from t_ignore; +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +select * from t_ignore; + +-- test for ustore table, opfusion: off +set enable_opfusion = off; +delete from t_ignore; +insert into t_ignore values(1); +explain(costs off) insert /*+ ignore_error */ into t_ignore values(1); +insert /*+ ignore_error */ into t_ignore values(1); +select * from t_ignore; +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +select * from t_ignore; + +-- test for segment table +drop table if exists t_ignore; +create table t_ignore(num int unique) with(segment = on); + +-- test for segment table, opfusion: on +set enable_opfusion = on; +insert into t_ignore values(1); +insert /*+ ignore_error */ into t_ignore values(1); +select * from t_ignore; +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +select * from t_ignore; + +-- test for segment table, opfusion: off +delete from t_ignore; +set enable_opfusion = off; +insert into t_ignore values(1); +insert /*+ ignore_error */ into t_ignore values(1); +select * from t_ignore; +insert into t_ignore values(2); +update /*+ ignore_error */ t_ignore set num = 1 where num = 2; +select * from t_ignore; + +\c postgres +drop database if exists sql_ignore_unique_test; \ No newline at end of file