diff --git a/src/gausskernel/optimizer/commands/trigger.cpp b/src/gausskernel/optimizer/commands/trigger.cpp index 0503f1e87..6b86257f4 100644 --- a/src/gausskernel/optimizer/commands/trigger.cpp +++ b/src/gausskernel/optimizer/commands/trigger.cpp @@ -85,6 +85,11 @@ (bms_union(exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->updatedCols, \ exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->extraUpdatedCols)) +#define B_TRIGGER_INLINE_STR "inlinefunc" +#define B_TRIGGER_INLINE_LENGTH 10 +#define B_TRIGGER_ID_LENGTH 8 /* for 65535 max = 5 chars, 3 '_' length total 8 */ +#define B_TRIGGER_ID_MAX 65530 /* max id search time we will report error */ + /* Local function prototypes */ static void ConvertTriggerToFK(CreateTrigStmt* stmt, Oid funcoid); static void SetTriggerFlags(TriggerDesc* trigdesc, const Trigger* trigger); @@ -96,6 +101,7 @@ static HeapTuple ExecCallTriggerFunc( static void AfterTriggerSaveEvent(EState* estate, ResultRelInfo* relinfo, uint32 event, bool row_trigger, Oid oldPartitionOid, Oid newPartitionOid, int2 bucketid, HeapTuple oldtup, HeapTuple newtup, List* recheckIndexes, Bitmapset* modifiedCols); +static char* rebuild_funcname_for_b_trigger(char* trigname, char* relname); #ifdef PGXC static bool pgxc_should_exec_triggers( Relation rel, uint16 tgtype_event, int16 tgtype_level, int16 tgtype_timing, EState* estate = NULL); @@ -537,10 +543,10 @@ ObjectAddress CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid r n->isPrivate = false; n->replace = false; n->definer = stmt->definer; - size_t funcNameLen = strlen(stmt->trigname) + strlen(stmt->relation->relname) + strlen("__inlinefunc") + 1; - char* funcNameTmp = (char*)palloc(funcNameLen); - ret = snprintf_s(funcNameTmp,funcNameLen, funcNameLen-1, "%s_%s_inlinefunc",stmt->trigname,stmt->relation->relname); - securec_check_ss(ret, "\0", "\0"); + char* trigname = pstrdup(stmt->trigname); + char* relname = pstrdup(stmt->relation->relname); + /* means we need to rebuild the function name */ + char* funcNameTmp = rebuild_funcname_for_b_trigger(trigname, relname); n->funcname = list_make1(makeString(funcNameTmp)); n->parameters = NULL; n->returnType = makeTypeName("trigger"); @@ -6319,3 +6325,54 @@ void ResetTrigShipFlag() } } +/* build a function name for b format trigger */ +static char* rebuild_funcname_for_b_trigger(char* trigname, char* relname) +{ + uint16 uid = 0; + char* funcname = NULL; + int ret = 0; + size_t funcNameLen = strlen(trigname) + strlen(relname) + B_TRIGGER_INLINE_LENGTH + B_TRIGGER_ID_LENGTH + 1; + size_t halfPos = (NAMEDATALEN - B_TRIGGER_INLINE_LENGTH - B_TRIGGER_ID_LENGTH) / 2 - 1; + /* reset overflow length */ + if (funcNameLen >= NAMEDATALEN) { + /* we have to reduce name string for oversize */ + if (strlen(trigname) > halfPos) { + trigname[halfPos - 1] = '\0'; + } + + if (strlen(relname) > halfPos) { + relname[halfPos - 1] = '\0'; + } + funcNameLen = strlen(trigname) + strlen(relname) + B_TRIGGER_INLINE_LENGTH + B_TRIGGER_ID_LENGTH + 1; + } + funcname = (char*)palloc0(sizeof(char) * funcNameLen); + CatCList* catlist = NULL; + do { + if (uid++ > B_TRIGGER_ID_MAX) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("You cannot create the trigger function because there are too many name conflicts."), + errdetail("We need to build a function internal, please rename the trigger."))); + } + ret = snprintf_s(funcname, funcNameLen, funcNameLen - 1, "%s_%s_%s_%hu", trigname, relname, B_TRIGGER_INLINE_STR, uid); + securec_check_ss(ret, "\0", "\0"); + if (t_thrd.proc->workingVersionNum < 92470) { + catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname)); + } else { + catlist = SearchSysCacheList1(PROCALLARGS, CStringGetDatum(funcname)); + } + if (catlist != NULL) { + if (catlist->n_members > 0) + ReleaseSysCacheList(catlist); + else { + ReleaseSysCacheList(catlist); + break; + } + } else { + break; + } + + } while (true); + + return funcname; +} \ No newline at end of file diff --git a/src/test/regress/expected/mysql_trigger.out b/src/test/regress/expected/mysql_trigger.out index 4fd4a3cdf..552ca1336 100644 --- a/src/test/regress/expected/mysql_trigger.out +++ b/src/test/regress/expected/mysql_trigger.out @@ -1001,6 +1001,57 @@ end; alter trigger testscm.animals_trigger2 on animals_scm rename to animals_trigger2_1; drop trigger testscm.animals_trigger2_1 on animals_scm; set search_path to public; +--bugfix for name long +drop table if exists T_ignore_case_in_dquotes_use_case0007; +NOTICE: table "t_ignore_case_in_dquotes_use_case0007" does not exist, skipping +drop table if exists T_ignore_case_in_dquotes_use_case0007_1; +NOTICE: table "t_ignore_case_in_dquotes_use_case0007_1" does not exist, skipping +create table T_ignore_case_in_dquotes_use_case0007(col1 int,col2 varchar(20)); +create table T_ignore_case_in_dquotes_use_case0007_1(col1 int,col2 varchar(20)); +create trigger Tri_ignore_case_in_dquotes_use_case0007 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0008 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0009 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +create trigger Tri_ignore_case_in_dquotes_use_case0011 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ +insert into T_ignore_case_in_dquotes_use_case0007 values(11,'test'); +select * from T_ignore_case_in_dquotes_use_case0007; + col1 | col2 +------+------ + 11 | test +(1 row) + +select * from T_ignore_case_in_dquotes_use_case0007_1; + col1 | col2 +------+-------- + 1 | INSERT + 1 | INSERT + 1 | INSERT + 1 | INSERT +(4 rows) + -- 1.5 cleanup \c regression drop database testdb_m; diff --git a/src/test/regress/output/trigger_dump.source b/src/test/regress/output/trigger_dump.source index e8c2a9d19..253887234 100644 --- a/src/test/regress/output/trigger_dump.source +++ b/src/test/regress/output/trigger_dump.source @@ -61,7 +61,7 @@ insert into old_dump values(2,2); ERROR: permission denied for relation tab_dump DETAIL: N/A CONTEXT: SQL statement "insert into tab_dump values(new.id,new.c1)" -PL/pgSQL function tri_dump_old_dump_inlinefunc() line 2 at SQL statement +PL/pgSQL function tri_dump_old_dump_inlinefunc_1() line 2 at SQL statement \c test2_dump --insert insert into old_dump values(2,2); @@ -84,7 +84,7 @@ insert into old_dump values(2,2); ERROR: permission denied for relation tab_dump DETAIL: N/A CONTEXT: SQL statement "insert into tab_dump values(new.id,new.c1)" -PL/pgSQL function tri_dump_old_dump_inlinefunc() line 2 at SQL statement +PL/pgSQL function tri_dump_old_dump_inlinefunc_1() line 2 at SQL statement \c regression drop database test_dump; drop database test1_dump; diff --git a/src/test/regress/sql/mysql_trigger.sql b/src/test/regress/sql/mysql_trigger.sql index 62debccbb..3056e80be 100644 --- a/src/test/regress/sql/mysql_trigger.sql +++ b/src/test/regress/sql/mysql_trigger.sql @@ -567,6 +567,52 @@ end; alter trigger testscm.animals_trigger2 on animals_scm rename to animals_trigger2_1; drop trigger testscm.animals_trigger2_1 on animals_scm; set search_path to public; + +--bugfix for name long +drop table if exists T_ignore_case_in_dquotes_use_case0007; +drop table if exists T_ignore_case_in_dquotes_use_case0007_1; +create table T_ignore_case_in_dquotes_use_case0007(col1 int,col2 varchar(20)); +create table T_ignore_case_in_dquotes_use_case0007_1(col1 int,col2 varchar(20)); + +create trigger Tri_ignore_case_in_dquotes_use_case0007 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +create trigger Tri_ignore_case_in_dquotes_use_case0008 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +create trigger Tri_ignore_case_in_dquotes_use_case0009 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + + +create trigger Tri_ignore_case_in_dquotes_use_case0011 +after insert on T_ignore_case_in_dquotes_use_case0007 +for each row +begin +insert into T_ignore_case_in_dquotes_use_case0007_1 values (1,'INSERT'); +end; +/ + +insert into T_ignore_case_in_dquotes_use_case0007 values(11,'test'); + +select * from T_ignore_case_in_dquotes_use_case0007; + +select * from T_ignore_case_in_dquotes_use_case0007_1; + -- 1.5 cleanup \c regression drop database testdb_m; @@ -620,6 +666,7 @@ for each row execute procedure food_insert_func(); alter trigger testscm_no.animals_trigger2 on testscm.animals_scm rename to animals_trigger2_1; drop trigger testscm_no.animals_trigger2; + -- 2.2 cleanup \c regression drop database testdb; \ No newline at end of file