YES. This is good stuff.

Thanks again.

On 3/16/07, Monty Taylor <[EMAIL PROTECTED]> wrote:
> On 3/15/07, Michael Bayer <[EMAIL PROTECTED]> wrote:
> >
> > well at least make a full blown patch that doesnt break all the other
> > DB's.  notice that an Engine doesnt just execute Compiled objects, it
> > can execute straight strings as well.  thats why the dialect's
> > do_execute() and do_executemany() take strings - they are assumed to
> > go straight to a DBAPI representation.  to take the "stringness" out
> > of Engine would be a large rework to not just Engine but all the
> > dialects.
> >
> > im surprised the execute_compiled() method works for you at all, as
> > its creating a cursor, calling result set metadata off the cursor,
> > etc. all these DBAPI things which you arent supporting.  it seems
> > like it would be cleaner for you if you werent even going through
> > that implementation of it.
>
> Well, I was trying my best to be a good citizen, so I made some
> classes that implement all of the methods that the pieces of
> execute_compiled seemed to want, faking it for now when I didn't need
> it. The semantics of most of the DBAPI map to the NDBAPI fairly well
> (it's still all the same underlying db ideas - just no sql strings)
>
> BUT...
>
> > the theme here is that the base Engine is assuming a DBAPI
> > underneath.  if you want an Engine that does not assume string
> > statements and DBAPI's it might be easier for you to just provide a
> > subclass of Engine instead (or go even lower level, subclass
> > sqlalchemy.sql.Executor).   either way you can change what
> > create_engine() returns by using a new "strategy" to create_engine(),
> > which is actually a pluggable API.  e.g.
>
> This seems like what I really want to try, because you are right,
> trying to get this to pretend to be totally DBAPI is going to be not
> totally fun. I'll see what trouble I get myself into this way... or
> I'll send a patch that changes all the internals. :)
>
> Thanks!
>
> > from sqlalchemy.engine.strategies import DefaultEngineStrategy
> >
> > class NDBAPIEngineStrategy(DefaultEngineStrategy):
> >    def __init__(self):
> >          DefaultEngineStrategy.__init__(self, 'ndbapi')
> >
> >      def get_engine_cls(self):
> >          return NDBAPIEngine
> >
> > # register the strategy
> > NDBAPIEngineStrategy()
> >
> > now you connect via:
> >
> > create_engine(url, strategy='ndbapi')
> >
> > if you want to go one level lower, which i think you do because you
> > dont really want pooling or any of that either, you dont even need to
> > have connection pooling or anything like that....you can totally
> > override what create_engine() does, have different connection
> > parameters, whatever.  just subclass EngineStrategy directly:
> >
> > class NDBAPIEngineStrategy(EngineStrategy):
> >      def __init__(self):
> >          EngineStrategy.__init__(self, 'ndbapi')
> >      def create(self, *args, **kwargs):
> >          # this is some arbitrary set of arguments
> >          return NDAPIEngine(kwargs.get('connect_string'), kwargs.get
> > ('some_other_argument'), new NDBAPIDialect(*args), etc etc)
> > # register
> > NBAPIEngineStrategy()
> >
> > then you just say:
> >
> > create_engine(connect_string='someconnectstring',
> > some_other_argument='somethingelse', strategy='ndbapi')
> >
> > i.e. whatever you want.  create_engine() just passes *args/**kwargs
> > through to create() after pulling out the "strategy" keyword.
> >
> > if you dont like having to send over "strategy" i can add a hook in
> > there to look it up on the dialect, so it could be more like
> > create_engine('ndbapi://whatever').  but anyway this method would
> > mean we wouldnt have to rewrite half of Engine's internals.
> >
> >
> > On Mar 14, 2007, at 7:28 PM, Monty Taylor wrote:
> >
> > >
> > > Hi - I'd attach this as a patch file, but it's just too darned
> > > small...
> > >
> > > I would _love_ it if we didn't automatically stringify compiled
> > > statements here in base.py, because there is no way to override this
> > > behavior in a dialect. I'm working on an NDBAPI dialect to support
> > > direct access to MySQL Cluster storage, and so I never actually have a
> > > string representation of the query. Most of the time this is fine, but
> > > to make it work, I had to have pre_exec do the actual execution,
> > > because by the time I got to do_execute, I didn't have my real object
> > > anymore.
> > >
> > > I know this would require some other code changes to actually get
> > > applied - namely, I'm sure there are other places now where the
> > > statement should be str()'d to make sense.
> > >
> > > Alternately, we could add a method to Compiled. (I know there is
> > > already get_str()) like "get_final_query()" that gets called in this
> > > context instead. Or even, although it makes my personal code less
> > > readable, just call compiled.get_str() here, which is the least
> > > invasive, but requires non-string queries to override a method called
> > > get_str() to achieve a purpose that is not a stringification.
> > >
> > > Other than this, so far I've actually got the darned thing inserting
> > > records, so it's going pretty well... other than a whole bunch of test
> > > code I put in to find out why it wasn't inserting when the problem was
> > > that I was checking the wrong table... *doh*
> > >
> > > Thanks!
> > > Monty
> > >
> > > === modified file 'lib/sqlalchemy/engine/base.py'
> > > --- lib/sqlalchemy/engine/base.py       2007-02-13 22:53:05 +0000
> > > +++ lib/sqlalchemy/engine/base.py       2007-03-14 23:17:40 +0000
> > > @@ -312,7 +312,7 @@
> > >             return cursor
> > >         context = self.__engine.dialect.create_execution_context()
> > >         context.pre_exec(self.__engine, proxy, compiled, parameters)
> > > -        proxy(str(compiled), parameters)
> > > +        proxy(compiled, parameters)
> > >         context.post_exec(self.__engine, proxy, compiled, parameters)
> > >         rpargs = self.__engine.dialect.create_result_proxy_args
> > > (self, cursor)
> > >         return ResultProxy(self.__engine, self, cursor, context,
> > > typemap=compiled.typemap, columns=compiled.columns, **rpargs)
> > > @@ -342,7 +342,7 @@
> > >         if cursor is None:
> > >             cursor = self.__engine.dialect.create_cursor
> > > (self.connection)
> > >         try:
> > > -            self.__engine.logger.info(statement)
> > > +            self.__engine.logger.info(str(statement))
> > >             self.__engine.logger.info(repr(parameters))
> > >             if parameters is not None and isinstance(parameters, list)
> > > and len(parameters) > 0 and (isinstance(parameters[0], list) or
> > > isinstance(parameters[0], dict)):
> > >                 self._executemany(cursor, statement, parameters,
> > > context=context)
> > >
> > > >
> >
> >
> > > >
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to