On 6/25/14, 5:35 PM, Jason Newton wrote: > > > > >> Hand crafted inserts use server side lo_create(-1) (in sql) which >> allocates a new large object and returning clause to get the oid >> in one go back to the client side. Then I start using the >> lobject api on the returned oid. > I'd like to see explicit SQL, preferably in the form of a psycopg2 > script that illustrates all the operations you wish to support and > specifically how they must interact with the database. > > > I've attached example usages. As I indicated in my prior email, right > now I only do inserts/selects. Here's my immediate thought about the INSERT (and the UPDATE) - the first way is using events, the second would attempt to move this system into something more native to the psycopg2 dialect:
Use the before_cursor_execute() and after_cursor_execute() events to get at this: http://docs.sqlalchemy.org/en/latest/core/events.html#sqlalchemy.events.ConnectionEvents.before_cursor_execute http://docs.sqlalchemy.org/en/latest/core/events.html#sqlalchemy.events.ConnectionEvents.after_cursor_execute 1. Create a new type called PGLOB or whatever you want. For starters, this can just be a blank UserDefinedType subclass. in before_cursor_execute: 2. determine if INSERT or UPDATE using context.isinsert, context.isupdate 3. examine the datatypes that SQLAlchemy is using here, by looking at context.compiled.binds. The values here are BindParameter objects, you want to look in those for the ones that are of type PGLOB. 4. From context.compiled.binds, you have the names of the bound params with the type. Search and replace the "statement" for occurrences of that bound parameter, replace with "lo_creat(-1)" or whatever you need there. 5. Also append to the RETURNING clause those cols you need. 6. the statement as a return value will be used, if you set up the event with retval=True (see the docs). in after_cursor_execute: 7. in after_cursor_execute - call fetchone() to get the RETURNING values. Get that OID you care about then do that work with conn.lobject and all that. hopefully this doesnt mess up the existing cursor state. 8. now the tricky part. SQLAlchemy needs that row if you're doing "implicit returning" to get at primary key values. psycopg2's cursor seems to have a scroll() method that works for client side cursors. I'd scroll it back one so that SQLA gets the state it expects. Alternative system, more plugged in: 1. We would be creating new features on sqlalchemy/dialects/postgresql/psycopg2.py -> PGExecutionContext_psycopg2. Similar hooks are available here which you can use to accomplish similar tasks; you'd want to look at the pre_exec(), post_exec() and possibly post_insert() methods, and maybe even _fetch_implicit_returning(). If SQLA were to support this more natively, things would be happening at this level. But again, I really wouldn't want all kinds of hardcoded expectations of LOB objects in this object taking up processing time for the vast majority of use cases that don't use LOBs, so the extra logic here should be contained within something that can easily be placed aside based on options or similar. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.