[stackoverflow] [progress Openedge Abl] Properly Implementing Auto-incrementing Primary...

Status
Not open for further replies.
A

Abe Voelker

Guest
I would like to mimic the auto-incrementing primary keys feature that many databases have in OpenEdge (i.e. to not have to specify the primary key value when doing an INSERT) using the JDBC adapter. So far, I've come very close to what I need, except for the part of being able to access the primary key value that the database generated on return from the INSERT (ahem, so maybe not that close ;)).

My current solution uses a combination of table PK default value, trigger and sequence in order to pull it off:

CREATE TABLE users (
id BIGINT PRIMARY KEY DEFAULT -1,
name VARCHAR(200)
);

CREATE SEQUENCE users_seq
START WITH 0,
INCREMENT BY 1,
NOCYCLE;

CREATE TRIGGER users_trigger
BEFORE INSERT ON users
REFERENCING NEWROW
FOR EACH ROW
IMPORT
import java.sql.*;
BEGIN
Long current_id = (Long)NEWROW.getValue(1, BIGINT);
if (current_id == -1) {
SQLCursor next_id_query = new SQLCursor("SELECT TOP 1 users_seq.NEXTVAL FROM SYSPROGRESS.SYSCALCTABLE");
next_id_query.open();
next_id_query.fetch();
Long next_id = (Long)next_id_query.getValue(1,BIGINT);
next_id_query.close();
NEWROW.setValue(1, next_id);
}
END


This allows me to run an insert statement like this:

INSERT INTO users(name) VALUES('Foo Bar')


and the new row automatically gets an ID from the database trigger. That part works fine.

What I really need now is the value of the ID that gets set; either to get the value directly, or a ResultSet that contains the row that just got inserted (that could then be unwrapped to view the ID). I know Oracle and Postgres both support a RETURNING clause for inserts, which is typically how this is handled. However, I don't see anything like that for OpenEdge.

The only relevant part I could find in the 10.2B SQL Development manual is in section 5-10, where it shows how to access the CURRVAL of a sequence after performing an INSERT that uses NEXTVAL. However, that's dangerous as I could get someone else's ID if there are a large amount of INSERTs going on for that table across multiple JDBC sessions (race conditions and whatnot).

The only alternative I can come up with so far is to write a stored procedure specifically for wrapping/performing the INSERT operation, that has an output parameter of the ID that gets generated. However, that isn't feasible for what I'm working on, which must use a plain SQL INSERT statement, and also seems a bit hackish and brittle (e.g. how to handle the different combinations and permutations of values that could be provided on the INSERT, and what if the schema changes?).

Also, the whole point of this is to not have to reference the primary key in the INSERT, so please don't tell me to use users_seq.NEXTVAL in my INSERT statement. :)

Continue reading...
 
Status
Not open for further replies.
Top