Robert Haas <robertmh...@gmail.com> writes: >> Given what I foresee, simply having another columns in there named >> evtstags with the exact same content as evttags would be the simplest >> and most natural implementation, really. > > That seems a lot less general for no particular gain.
The gain is code, docs and usage simplification. I think going general here is going to confuse every one involved and that we should have two targets in mind: classic use cases that we want to address easily enough in SQL and with some PLpgSQL help, and advanced use cases that are possible to implement in PL/C using the parse tree and the soon to come back rewritten command string. IOW, let's make the simple things simple and the complex one possible. The following is quite long an email where I try to give plenty of examples and to detail the logic I'm working with so that you can easily stab at whichever part you're thinking is not going to fly. >> I don't foresee more generic needs here, unless you can convince me that >> we need both a. a full stack of arbitrarily nested commands and b. a way >> to match and target any level of that stack. > > Well, let's take the example of an ALTER TABLE command. You could > want to match on: > > - the type of object the user mentioned in the command (did he write > ALTER TABLE or ALTER VIEW?) > - the type of object actually being modified (could differ if he used I don't think it's possible to implement that without shaking all the system, after having a look at the following lines from gram.y: ALTER VIEW qualified_name alter_table_cmds { AlterTableStmt *n = makeNode(AlterTableStmt); So, the way to implement that need from an event trigger is to use the parse tree, and hopefully soon enough the rewritten command string. > ALTER TABLE on a view, or visca versa) > - the particular ALTER TABLE subcommand in use (e.g. SET STATISTICS) Now we can publish that, we would have some events with tag = 'ALTER TABLE' then some others with toplevel = 'ALTER TABLE' tag = 'SET STATISTICS' The same idea would need to get implemented for serial, where the tag is 'CREATE SEQUENCE' and the toplevel tag is 'CREATE TABLE'. That allows to easily install an event trigger that gets called every time a sequence is created, you can then have a look at the toplevel command tag if you need to. CREATE EVENT TRIGGER snitch_seqs ON command_start WHEN tag IN ('CREATE SEQUENCE') EXECUTE PROCEDURE snitch_seqs(); The idea is that the function snitch_seqs has a "magic" variable TG_TOPLEVEL that can be tested and will be set to 'CREATE TABLE' when we're dealing with a SERIAL, in that example. If you want your event trigger to only ever deal with SERIAL, you could install it this way: CREATE EVENT TRIGGER my_serial_trigger ON command_start WHEN toplevel IN ('CREATE TABLE') AND tag IN ('CREATE SEQUENCE') EXECUTE PROCEDURE handle_serial_trigger(); Now let's see about getting more generic than that. We also can get tag = 'CREATE INDEX' and toplevel = 'ALTER TABLE' when adding a primary key for example. That's an example that can lead us to more than 2 levels of nested tags, which I would want to avoid. The stack here would look like: 1. ALTER TABLE 2. ADD PRIMARY KEY 3. CREATE INDEX I think only having 1 and 3 is enough, for more details the command string and the parse tree are available. In the main use case of replication, you mostly just want to replicate the command string. You might want to apply some transformation rules to it (table names, cope with a different target schema, etc) but typically those rules are to be run in the subscriber system, not on the provider (picture a federating system where each provider uses the same schema, that gets mapped to a schema per provider on the subscriber). The other problem with the stack of tags is matching them. I don't see that it helps writing event triggers much. In the previous example, if you want an event trigger that fires on each ALTER TABLE, you don't know which level of the stack to target. Either you have to target the current tag or the toplevel tag or something in between. We could easily have the following tag stack: 1. CREATE SCHEMA 2. ALTER TABLE 3. ADD PRIMARY KEY 4. CREATE INDEX So now we need a way to target any entry in the stack and a way to represent the stack in every PL language we have, and an easy way to analyze the stack. For PLpgSQL I guess that means we want to expose this tag stack as a TABLE, and the complexity just went off the table. My view point is that for any practical case I can think about what we care about is the current command being run, and given how PostgreSQL is made today that means handling one level of sub commands. That addresses ALTER TABLE and also DROP CASCADE. I don't think adding-in an ALTER TABLE that never happened in the middle of those two elements is going to make life easier for anybody involved, quite the contrary: 1. DROP TYPE 2. DROP COLUMN Users that need that level of detail for their processing are welcome to code their Event Trigger in PL/C and analyze the parse tree. We can call that advanced analysis. > I suspect there are other examples as well. If we pick the 2-D list > representation I suggested, or something like it, we can easily > accommodate these kinds of filters without having to whack the catalog > representation around any further. That seems pretty appealing. The generic approach leads us to invent a stack of tags and (I suspect) a DSL for tag matching where you can express at least those different things: - this tag is found in the stack (tag <@ stack) - this other tag is found higher in the stack - this other tag is found just one level higher in the stack - this other tag is found at least 2 levels higher in the stack - this third tag is found lower in the stack - this third tag is found just one level lower in the stack - and maybe some more Those semantics are going to be needed, either in the event trigger definition itself, or in the event trigger code. We could expose a stack of tags and ditch the WHEN clause here, but we still have to be able to implement the filtering in PLpgSQL for simple cases. If we're not able to express such detailed semantics I don't think we're servicing users by making things way more complex for them to use. The drawback is that we will have to make choices as to which tag we expose exactly, remembering that all the details are to be found in the parse tree and the rewritten command string. Regards, -- Dimitri Fontaine http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers