How would you ignore a trigger within a trigger? #190
-
I am updating This works without the Model TblA(models.Model):
field_1 = models.CharField(max_length=20)
field_2 = models.PositiveIntegerField(default=0)
class Meta:
triggers = [
pgtrigger.ReadOnly(
name='read_only_field_2',
fields=['field_2']
)
] class TblB(models.Model):
field_a = models.ForeignKey(TblA, on_delete=models.SET_NULL)
class Meta:
pgtrigger.Trigger(
func=pgtrigger.Func('''
IF (NEW."{columns[field_a]}" IS NOT NULL) THEN
UPDATE "tbla"
SET "tbla"."field_2" = "tbla"."field_2" + 1
WHERE
"tbla"."id" = NEW.{columns[field_a]}
END IF;
RETURN NEW;
''')
),
when=pgtrigger.Before,
operation=pgtrigger.Insert,
name='increment_tbla_field_2'
), I was thinking to mimic pgtrigger.ignore() functionality within the trigger by using set_config however I am not very familiar how persistent set_config is. Do I need to clean up at the end of the trigger? Is this doable?
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
The approach you outlined is likely the best approach for now. The main potential side effect is overriding any triggers your app has previously ignored during the duration of this transaction. For example, if you did I'd be open for a PR that adds |
Beta Was this translation helpful? Give feedback.
-
Thank you for a fast reply! I glanced at the (excellent) source code to see how would you add a SELECT CURRENT_SETTING('pgtrigger.ignore') into _prev_ignore;
SELECT _prev_ignore::text[] || '{uri,pgid}'::text[] into _local_ignore;
SELECT set_config('pgtrigger.ignore', _local_ignore::text, true); Afterwards SELECT set_config('pgtrigger.ignore, _prev_ignore, true)
RETURN RESULT But this would require to use a second wrapping function to reset the |
Beta Was this translation helpful? Give feedback.
-
I made it work like so: Model TblA(models.Model):
field_1 = models.CharField(max_length=20)
field_2 = models.PositiveIntegerField(default=0)
class Meta:
triggers = [
pgtrigger.ReadOnly(
name='read_only_field_2',
fields=['field_2']
)
]
class TblB(models.Model):
field_a = models.ForeignKey(TblA, on_delete=models.SET_NULL)
class Meta:
triggers = [
pgtrigger.Trigger(
func=pgtrigger.Func('''
BEGIN
SELECT CURRENT_SETTING('pgtrigger.ignore', true) INTO _prev_ignore;
EXCEPTION WHEN OTHERS THEN
END;
IF _prev_ignore IS NOT NULL AND (_prev_ignore = '') IS NOT TRUE THEN
SELECT _local_ignore || _prev_ignore::text[] INTO _local_ignore;
END IF;
PERFORM set_config('pgtrigger.ignore', _local_ignore::text, true);
IF (NEW."{columns[field_a]}" IS NOT NULL) THEN
UPDATE "tbla"
SET "tbla"."field_2" = "tbla"."field_2" + 1
WHERE
"tbla"."id" = NEW.{columns[field_a]}
END IF;
IF _prev_ignore IS NOT NULL AND (_prev_ignore = '') IS NOT TRUE THEN
PERFORM set_config('pgtrigger.ignore', _prev_ignore, true);
ELSE
PERFORM set_config('pgtrigger.ignore', '', true);
END IF;
RETURN NEW;
''')
),
when=pgtrigger.Before,
operation=pgtrigger.Insert,
name='increment_tbla_field_2',
declare=[
('_prev_ignore', 'text'),
('_local_ignore', f"text[] = '{{{TblA._meta.db_table}:{TblA._meta.triggers[0].get_pgid(TblA)},{TblA._meta.triggers[0].get_pgid(TblA)}}}'"),
]
),
] |
Beta Was this translation helpful? Give feedback.
I made it work like so: