[WIP][RFC]sequences support #186
Description
- Explicit sequence with string or array identifier
- Multiple sequences per table (would love ideas for improvement)
- Implicit sequence with column name only for
SERIAL
pseudo-type- Generate based on PostgreSQL concatenation rule
- Query database metadata if identifier ends up being longer than 63 bytes
- Add
SERIAL
pseudo-type to column creation DDL to compliment idea of implicit sequence at DB creation/migrations level. - Update
Insert
andUpdate
statements to filter out or generate values based on the changes - Consider making
SequenceFeature
independent fromTableGateway
since (1) it does not necesseirly tie to a specific table, (2) fixRowGateway
limitation - Update Metadata TableGateway feature to recognize SERIAL columns and add SequenceFeature instances
- Add MS SQL Server 2016 support
- Stretch goal: add Oracle 12c implicit sequence support
No BC breaks.
Thought process history
While reviewing #172, helping with #162, and fresh out of a heavy database driven enterprise platform contract, noticed how deficient current sequence support is plus misleading function signatures. This is an important feature because, better than auto_increment in PostgreSQL, the only way to increment Oracle, and now Microsoft brought it in due to popular demand in SQL Server 2016 so I feel it needs detailed look.
Current situation is that:
- TableGateway can only deal with a single sequence instance primarily for primary key usage, despite accepting unrestricted number of features.
- As pointed out by @andrey-mokhov only supports explicit sequence naming. In some engines like Oracle, MSSQL2016 this is fine, but PostgreSQL supports auto-generated sequence names with SERIAL which is a problem.
- Discovered at Primary keys (Sequence) not setting after save #191 that RowGateway is also incapable of handling sequences. Limitation is in fact that RowGateway does not link to any table gateway. Easy to add as an optional dependency by making constructor support TableGateway along with string and TableIdentifier OR add addition of features like other db classes, but hard in that INSERT operation on new record cannot be engine augnostic. May need to explicitly check for existence of that feature even if it breaks good OOP practice (or better suggestion).
What I have seen in the field:
- Sequences are not always used for primary key generation. I experienced this myself, is documented at https://msdn.microsoft.com/en-us/library/ff878058.aspx and requested in our Hibernate neighbours http://stackoverflow.com/questions/277630/hibernate-jpa-sequence-non-id
- Multiple sequences for a table, one for primary key, others for auto-incrementing based on some business rule, are not uncommon. Think invoice number generator across multiple sales departments, worker queue management, etc.
- Mix of implicit sequence names (usually for PK) and explicitly named in schema (usually for business rules)
Submitted PR #187 where I got around multiple features of same type problem. Intended usage would be (documented of course when settled one one)
$tableGateway = new TableGateway('table', $adapter, [new Sequence('pk_column', 'seq_1'), new Sequence('seq_2')]);
$tableGateway->nextSequenceId(); // no parameter aimed at 'seq_1' implying primary key
$tableGateway->nextSequenceId('seq_2'); // parameter specifying which one of the participating sequences are interested in
Why not always let developers manually handle Sequence objects without attaching them to table gateway? In large schemas, relationships set by architect can be difficult to keep in mind and I caused horrible bugs not being aware of what sequence participates in what business logic transaction. Using tablegateway to group them together helps a lot.
Now undecided on how to deal with preInsert/postInsert and dependence on gateway, how would I optionally mark one of several sequences that is used in TableGateway as responsible for PK? How would lastInsertValue be managed for multiple autoincremented columns?