[sqlalchemy] Enclose each test in a transaction

2013-06-07 Thread Victor Varvariuc
Hi!

I am trying to make a base class for our tests, that after each test case 
all the changes made by tests and the tested code are rolled back.
I saw the pattern here 
http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#joining-a-session-into-an-external-transaction,
 
but i have some problems.

class BaseTest(unittest.TestCase):


http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#joining-a-session-into-an-external-transaction

def __call__(self, result=None):

Wrapper around default __call__ method to perform common test
set up. This means that user-defined Test Cases aren't required to
include a call to super().setUp().

testMethod = getattr(self, self._testMethodName)
skipped = (getattr(self.__class__, __unittest_skip__, False) or
getattr(testMethod, __unittest_skip__, False))

if not skipped:
try:
self._pre_setup()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
result.addError(self, sys.exc_info())
return
super(BaseTest, self).__call__(result)
if not skipped:
try:
self._post_teardown()
except (KeyboardInterrupt, SystemExit):
raise
except Exception:
result.addError(self, sys.exc_info())
return

def _pre_setup(self):
# connect to the database
self._connection = apilib.engine.connect()
# begin a non-ORM transaction
self._transaction = self._connection.begin()
# make apilib.Session to be inside our transaction
apilib.Session.configure(bind=self._connection)
self.session = sessionmaker(bind=self._connection)()

def _post_teardown(self):
# roll back all changes made by the tests
self._transaction.rollback()
self.session.close()
apilib.Session.configure(bind=apilib.engine)
# return connection to the Engine
self._connection.close()


1. The tests code uses apilib.Session, while the tests use self.session.
2. Looks like if in code some does an additional session.rollback(), all 
the enclosing transaction is rolled back, and all objects created in 
setUp() (which use self.session) are lost.
3. Did i do correctly that i made the tested code use the session with test 
connection in transaction? Otherwise i guess sessions in the tested code 
and test itself would be in different transactions, and the tested code 
would not see changes made in setUp()
4. Is this the best pattern for our needs?

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] [Q][0.7.9] problem with with_entities(), over() and label()

2013-06-07 Thread Ladislav Lenart
On 6.6.2013 19:33, Michael Bayer wrote:
 
 On Jun 6, 2013, at 12:56 PM, Ladislav Lenart lenart...@volny.cz wrote:
 
 Hello.

 I have already solved the issue by using subquery:

 SELECT
t.id AS t_id,
t.rownum AS t_rownum
 FROM (
SELECT
FROM
foo.id AS id,
row_number() OVER (ORDER BY foo.id) AS rownum
 ) AS t
 WHERE rownum % 50 = 1

 I have just tried your suggestion about using HAVING instead of WHERE, but 
 that
 fails with the same error. Thus a label cannot be used inside a query.

 However, I am still curious whether the original WindowedRangeQuery recipe at

http://www.sqlalchemy.org/trac/wiki/UsageRecipes/WindowedRangeQuery

 works or also has this error.
 
 the recipe as you noted uses from_self(), which means, wrap myself in a 
 subquery, so that's where the necessary subquery is applied.

That explains it :-)


Thank you,

Ladislav Lenart

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] [ANN] Modified WindowedRangeQuery recipe

2013-06-07 Thread Ladislav Lenart
Hello.

I modified the recipe at

http://www.sqlalchemy.org/trac/wiki/UsageRecipes/WindowedRangeQuery

to better suit my needs. Perhaps someone else will find this useful:



 CODE BEGIN 


from sqlalchemy.orm import subqueryload
from sqlalchemy.sql.expression import distinct

def windowed_query(filter_query, data_query, column, window_size):
Perform (a correct) yield_per() operation. See WindowedQuery.yield_per()
for more.

EXAMPLE:
gen = windowed_query(
filter_query=session.query(Foo).filter(Foo.name.like(u'%foo%')),
data_query=session.query(Foo).options(Foo.bars),
column=Foo.id,
window_size=50,
)
for each_foo in gen:
print each_foo.name
for each_bar in each_foo.bars:
print each_bar

return WindowedQuery(filter_query, data_query, 
column).yield_per(window_size)

class WindowedQuery(object):
Perform (a correct) yield_per() operation.
def __init__(self, filter_query, data_query, column):
# A query with NO options(...) and NO order_by(...). MUST contain all
# necessary join() and filter() to limit the result set as desired.
self._filter_query = filter_query
# A simple query with options() to fetch the actual data.
self._data_query = data_query
# id column of the (main) result ORM class.
self._column = column

def yield_per(self, window_size):
Process results in chunks.
Steps:
* Obtain ids of ALL result rows via self._filter_query.
* Divide ids to chunks of equal size and perform ONE query for EACH
chunk to fetch the data via self._data_query.

A chunk is determined by the test q.filter(self._column.in_(chunk)).
This is the only way that works in presence of the read-committed
isolation level.

q = self._data_query
for each_window in self._windows(window_size):
for each_result in q.filter(each_window):
yield each_result

def _windows(self, window_size):
chunk = []
chunk_size = 0
for each in self._q_column():
if chunk_size  window_size:
chunk.append(each)
chunk_size += 1
if chunk_size == window_size:
yield self._window_for_chunk(chunk)
chunk = []
chunk_size = 0
if chunk_size  0:
yield self._window_for_chunk(chunk)

def _q_column(self):
# distinct() ensures that each id is returned at most once despite
# a possible multiplying effect of a join().
return self._filter_query.with_entities(distinct(self._column))

def _window_for_chunk(self, chunk):
return self._column.in_(chunk)

##
 CODE END 
##


MOTIVATION: I have learned recently that Query.yield_per() does not work nicely
in combination with subqueryload(). The above recipe fixes that. Unfortunately
its usage is not as elegant and simple as q.yield_per(...).

If you have any idea how to accomplish the same with ONE query only (in SA 
0.7.9):

def windowed_query(query, column, window_size):
query --magic- filter_query
query --magic- data_query
...

I would very much like to hear about it.


PERFORMANCE: My first tests suggest that it might be one order of magnitude
better than the Query.yield_per() we use now.

Note also that yield_per() with subqueryload() was still about twice as fast as
the same query without yield_per(). But this will be highly dependent on the
query I guess.


WARNING: We do not use this in the production yet. Use at your own risk.


Happy SA hacking,

Ladislav Lenart

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] Simple [?] question about column prefixes

2013-06-07 Thread Richard Gerd Kuesters

Hi all!

I'm refactoring a database schema but I need it to mantain reverse 
compatibility with older versions of our software - using views.


But, to avoid confusion to other developers, new tables have two 
underscores as a prefix, like:



class Base(object):

@declared_attr
def __tablename__(cls):
return __%s % to_python_case(cls.__name__)


Now I want to add column prefixes too. I know I can append to this Base 
object:


__mapper_args__ = dict(
column_prefix='_'
)

But, when I inherit this new base on classes that I need to use 
__mapper_args__, column names probably won't have prefixes. Any ideas, 
perhaps an event listener to prepend the underscore into *all* column names?



Cheers,
Richard.

--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] [BUG][PATCH] Function names not quoted when necessary

2013-06-07 Thread Michael Bayer
logged this as http://www.sqlalchemy.org/trac/attachment/ticket/2749


On Jun 6, 2013, at 10:27 PM, Ryan Kelly rpkell...@gmail.com wrote:

 Function names in SQL can contain pretty much anything, e.g.:
 
 =# create function A Bug?(integer) returns integer as $$ select $1; $$ 
 language sql;
 CREATE FUNCTION
 
 But when attempting to use the function from SQLAlchemy:
 
 from sqlalchemy.sql.expression import func
 bug = getattr(func, A Bug?)(1)
 session.query(bug).all()
 
 ProgrammingError: (ProgrammingError) syntax error at or near ?
 LINE 1: SELECT A Bug?(1) AS A Bug?_1
 'SELECT A Bug?(%(A Bug?_2)s) AS A Bug?_1' {'A Bug?_2': 1}
 
 -Ryan P. Kelly
 
 -- 
 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?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
 
 
 quote_function_names.patch

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Enclose each test in a transaction

2013-06-07 Thread Michael Bayer

On Jun 7, 2013, at 3:29 AM, Victor Varvariuc victor.varvar...@gmail.com wrote:

 
 1. The tests code uses apilib.Session, while the tests use self.session.

well depends on what you're testing, if the tests go out to logic which refers 
to the global apilib.Session, that's fine


 2. Looks like if in code some does an additional session.rollback(), all the 
 enclosing transaction is rolled back, and all objects created in setUp() 
 (which use self.session) are lost.

yeah this whole recipe does not accomodate tests that do a rollback() in the 
middle, then continue going.

 3. Did i do correctly that i made the tested code use the session with test 
 connection in transaction? Otherwise i guess sessions in the tested code and 
 test itself would be in different transactions, and the tested code would not 
 see changes made in setUp()

seems like ?


 4. Is this the best pattern for our needs?

shrugs ?

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Simple [?] question about column prefixes

2013-06-07 Thread Michael Bayer

On Jun 7, 2013, at 9:31 AM, Richard Gerd Kuesters rich...@humantech.com.br 
wrote:

 Hi all!
 
 I'm refactoring a database schema but I need it to mantain reverse 
 compatibility with older versions of our software - using views.
 
 But, to avoid confusion to other developers, new tables have two underscores 
 as a prefix, like:
 
 
 class Base(object):
 
 @declared_attr
 def __tablename__(cls):
 return __%s % to_python_case(cls.__name__)
 
 
 Now I want to add column prefixes too. I know I can append to this Base 
 object:
 
 __mapper_args__ = dict(
 column_prefix='_'
 )
 
 But, when I inherit this new base on classes that I need to use 
 __mapper_args__, column names probably won't have prefixes. Any ideas, 
 perhaps an event listener to prepend the underscore into *all* column names?

one idea is you can intercept how mapper() is called by declarative by 
overriding __mapper_cls__, like:

@classmethod
def __mapper_cls__(cls, *args, **kw):
kw['column_prefix'] = '_'
return mapper(*args, **kw)





 
 
 Cheers,
 Richard.
 
 -- 
 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?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.
  
  

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Query and compiled_cache

2013-06-07 Thread Claudio Freire
On Thu, Jun 6, 2013 at 2:20 PM, Michael Bayer mike...@zzzcomputing.com
wrote:

 diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
 index c2ec72c..b458975 100644
 --- a/lib/sqlalchemy/orm/query.py
 +++ b/lib/sqlalchemy/orm/query.py
 @@ -40,12 +40,15 @@ from ..sql import (
  __all__ = ['Query', 'QueryContext', 'aliased']


 -def _generative(*assertions):
 +def _generative(*assertions, maintain_baked=False):
  Mark a method as generative.

  @util.decorator
  def generate(fn, *args, **kw):
  self = args[0]._clone()
 +if not maintain_baked:
 +del self._baked_cache
 +del self._baked_context
  for assertion in assertions:
  assertion(self, fn.func_name)
  fn(self, *args[1:], **kw)
 @@ -1157,7 +1160,7 @@ class Query(object):

  self._lockmode = mode

 -@_generative()
 +@_generative(maintain_baked=True)
  def params(self, *args, **kwargs):
  add values for bind parameters which may have been
  specified in filter().


That doesn't seem to be enough.

subqueryload seems to be using the wrong query still, after clearing the
baked context, resulting in some very wrong sharing of connections between
threads (I'm getting some very fun segmentation faults).

I think it's with_parent, it clears the baked context through a filter, but
the filter is called on the wrong query (the global query instance I use as
template), that has the wrong session attached or something.

This is my current BakedQuery:

 class BakedQuery(sqlalchemy.orm.query.Query):

_baked_context = None

_baked_cache = None


 def _clone(self):

rv = super(BakedQuery, self)._clone()

try:

del rv._baked_context

del rv._baked_cache

except AttributeError:

pass

return rv


 def params(self, *p, **kw):

rv = super(BakedQuery, self).params(*p, **kw)

rv._baked_context = self._baked_context

rv._baked_cache = self._baked_cache

return rv

 def with_session(self, *p, **kw):

rv = super(BakedQuery, self).with_session(*p, **kw)

rv._baked_context = self._baked_context

rv._baked_cache = self._baked_cache

return rv

 @sqlalchemy.orm.query._generative()

def bake_as(self, name, cache):

Freeze the statement used by this Query.


 if name not in cache:

cache[name] = context = self._compile_context()

del context.session

del context.query

self._baked_context = cache[name]

self._baked_cache = cache


 def _compile_context(self, **kw):

if self._baked_context is not None:

QueryContext = sqlalchemy.orm.query.QueryContext

context = QueryContext.__new__(QueryContext)

context.__dict__.update(self._baked_context.__dict__)

context.query = self

context.session = self.session

# need to fix these names, urg

context.attributes = context._attributes = context.attributes.copy()

return context

else:

return super(BakedQuery, self)._compile_context(**kw)


 def _execute_and_instances(self, querycontext):

if self._baked_cache is not None:

self = self.execution_options(compiled_cache=self._baked_cache)

return super(BakedQuery, self)._execute_and_instances(querycontext)



And I invoke it like:


def some_function(query = blabla.bake_as(blablah)):

return query.with_session(S).params(...).first()


This code still breaks if I don't use a baked template:


def some_function(query = blabla):

return query.with_session(S).bake_as(blablah).params(...).first()

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Query and compiled_cache

2013-06-07 Thread Claudio Freire
On Fri, Jun 7, 2013 at 1:56 PM, Claudio Freire klaussfre...@gmail.com wrote:

 This is my current BakedQuery:

 class BakedQuery(sqlalchemy.orm.query.Query):



F**k gmail again. Why the F+!k doesn't it show me that it'll bork all
whitespace before I hit send... I smell a bug report coming...

class BakedQuery(sqlalchemy.orm.query.Query):
._baked_context = None
._baked_cache = None
.
.def _clone(self):
.rv = super(BakedQuery, self)._clone()
.try:
.del rv._baked_context
.del rv._baked_cache
.except AttributeError:
.pass
.return rv
.
.def params(self, *p, **kw):
.rv = super(BakedQuery, self).params(*p, **kw)
.rv._baked_context = self._baked_context
.rv._baked_cache = self._baked_cache
.return rv
.
.def with_session(self, *p, **kw):
.rv = super(BakedQuery, self).with_session(*p, **kw)
.rv._baked_context = self._baked_context
.rv._baked_cache = self._baked_cache
.return rv
.
.@sqlalchemy.orm.query._generative()
.def bake_as(self, name, cache):
.Freeze the statement used by this Query.
.
.if name not in cache:
.cache[name] = context = self._compile_context()
.del context.session
.del context.query
.self._baked_context = cache[name]
.self._baked_cache = cache
.
.def _compile_context(self, **kw):
.if self._baked_context is not None:
.QueryContext = sqlalchemy.orm.query.QueryContext
.context = QueryContext.__new__(QueryContext)
.context.__dict__.update(self._baked_context.__dict__)
.context.query = self
.context.session = self.session
.# need to fix these names, urg
.context.attributes = context._attributes =
context.attributes.copy()
.return context
.else:
.return super(BakedQuery, self)._compile_context(**kw)
.
.def _execute_and_instances(self, querycontext):
.if self._baked_cache is not None:
.self = self.execution_options(compiled_cache=self._baked_cache)
.return super(BakedQuery, self)._execute_and_instances(querycontext)

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Simple [?] question about column prefixes

2013-06-07 Thread Richard Gerd Kuesters

Thank you Mike!

That brings me to another question:

Let's say I have created a simple table (well, I have):

class Language(Base):
language_id = Column(Integer, Sequence('language_id_seq', 
optional=True), primary_key=True)

language = Column(String(5), unique=True, default='undef')

The problem is (using pdb):

(Pdb) lang = Language(language='test')
(Pdb) lang
Language(language='test')
(Pdb) dir(lang)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__mapper__', 
'__mapper_cls__', '__module__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__table__', '__tablename__', '__weakref__', 
'_cls_id', '_decl_class_registry', '_has', '_language', '_language_id', 
'_sa_class_manager', '_sa_instance_state', 'id_', 'language', 
'language_id', 'metadata', 't']

(Pdb) session.add(lang)
(Pdb) session.commit()
(Pdb) lang2 = Language(language='foo')
(Pdb) session.add(lang2)
(Pdb) session.commit()
*** IntegrityError: (IntegrityError) column language is not unique 
u'INSERT INTO ht__language (language) VALUES (?)' ('undef',)

(Pdb) session.rollback()
(Pdb) session.query(Language).all()
[Language(language='test')]
(Pdb) lang2 = Language()
(Pdb) lang2.language = 'foo'
(Pdb) session.add(lang2)
(Pdb) session.commit()
*** IntegrityError: (IntegrityError) column language is not unique 
u'INSERT INTO ht__language (language) VALUES (?)' ('undef',)

(Pdb) session.rollback()
(Pdb) lang2 = Language()
(Pdb) lang2._language = 'foo'
(Pdb) session.add(lang2)
(Pdb) session.commit()
(Pdb) session.query(Language).all()
[Language(), Language(language='test')]

If I change the Language class to this:

class Language(Base):
language_id = Column(Integer, Sequence('language_id_seq', 
optional=True), primary_key=True)

language = Column('language', String(5), unique=True, default='undef')

The same happens. Curiously:

(Pdb) session.query(Language).all()
[Language(), Language(language='test')]
(Pdb) map(lambda a: a._language, session.query(Language).all())
[u'foo', u'undef']

Is there a problem using this mapper configuration with declarative bases?

Cheers,
Richard.



On 06/07/2013 11:46 AM, Michael Bayer wrote:


On Jun 7, 2013, at 9:31 AM, Richard Gerd Kuesters 
rich...@humantech.com.br mailto:rich...@humantech.com.br wrote:



Hi all!

I'm refactoring a database schema but I need it to mantain reverse 
compatibility with older versions of our software - using views.


But, to avoid confusion to other developers, new tables have two 
underscores as a prefix, like:



class Base(object):

@declared_attr
def __tablename__(cls):
return __%s % to_python_case(cls.__name__)


Now I want to add column prefixes too. I know I can append to this 
Base object:


__mapper_args__ = dict(
column_prefix='_'
)

But, when I inherit this new base on classes that I need to use 
__mapper_args__, column names probably won't have prefixes. Any 
ideas, perhaps an event listener to prepend the underscore into *all* 
column names?


one idea is you can intercept how mapper() is called by declarative by 
overriding __mapper_cls__, like:


@classmethod
def __mapper_cls__(cls, *args, **kw):
kw['column_prefix'] = '_'
return mapper(*args, **kw)








Cheers,
Richard.

--
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 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.

Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] [ANN] Modified WindowedRangeQuery recipe

2013-06-07 Thread Ladislav Lenart
Hello.

Resending because the original e-mail does not seem to make it to the mailing
list. Apologise for any duplicates. Here we go...


Hello.

I modified the recipe at

http://www.sqlalchemy.org/trac/wiki/UsageRecipes/WindowedRangeQuery

to better suit my needs. Perhaps someone else will find this useful:



 CODE BEGIN 


from sqlalchemy.orm import subqueryload
from sqlalchemy.sql.expression import distinct

def windowed_query(filter_query, data_query, column, window_size):
Perform (a correct) yield_per() operation. See WindowedQuery.yield_per()
for more.

EXAMPLE:
gen = windowed_query(
filter_query=session.query(Foo).filter(Foo.name.like(u'%foo%')),
data_query=session.query(Foo).options(Foo.bars),
column=Foo.id,
window_size=50,
)
for each_foo in gen:
print each_foo.name
for each_bar in each_foo.bars:
print each_bar

return WindowedQuery(filter_query, data_query, 
column).yield_per(window_size)

class WindowedQuery(object):
Perform (a correct) yield_per() operation.
def __init__(self, filter_query, data_query, column):
# A query with NO options(...) and NO order_by(...). MUST contain all
# necessary join() and filter() to limit the result set as desired.
self._filter_query = filter_query
# A simple query with options() to fetch the actual data.
self._data_query = data_query
# id column of the (main) result ORM class.
self._column = column

def yield_per(self, window_size):
Process results in chunks.
Steps:
* Obtain ids of ALL result rows via self._filter_query.
* Divide ids to chunks of equal size and perform ONE query for EACH
chunk to fetch the data via self._data_query.

A chunk is determined by the test q.filter(self._column.in_(chunk)).
This is the only way that works in presence of the read-committed
isolation level.

q = self._data_query
for each_window in self._windows(window_size):
for each_result in q.filter(each_window):
yield each_result

def _windows(self, window_size):
chunk = []
chunk_size = 0
for each in self._q_column():
if chunk_size  window_size:
chunk.append(each)
chunk_size += 1
if chunk_size == window_size:
yield self._window_for_chunk(chunk)
chunk = []
chunk_size = 0
if chunk_size  0:
yield self._window_for_chunk(chunk)

def _q_column(self):
# distinct() ensures that each id is returned at most once despite
# a possible multiplying effect of a join().
return self._filter_query.with_entities(distinct(self._column))

def _window_for_chunk(self, chunk):
return self._column.in_(chunk)

##
 CODE END 
##


MOTIVATION: I have learned recently that Query.yield_per() does not work nicely
in combination with subqueryload(). The above recipe fixes that. Unfortunately
its usage is not as elegant and simple as q.yield_per(...).

If you have any idea how to accomplish the same with ONE query only (in SA 
0.7.9):

def windowed_query(query, column, window_size):
query --magic- filter_query
query --magic- data_query
...

I would very much like to hear about it.


PERFORMANCE: My first tests suggest that it might be one order of magnitude
better than the Query.yield_per() we use now.

Note also that yield_per() with subqueryload() was still about twice as fast as
the same query without yield_per(). But this will be highly dependent on the
query I guess.


WARNING: We do not use this in the production yet. Use at your own risk.


Happy SA hacking,

Ladislav Lenart

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Simple [?] question about column prefixes

2013-06-07 Thread Michael Bayer
OK, the prefix is on the mapped attribute name, not the column.So 
Language(_language = 'foo').

Guess you're looking for the opposite, huh. This gets more weird but this 
should work, the main difficulty is limiting the columns being altered to just 
those within a certain class hierarchy, if you wanted to do it based on 
table.name.startswith('__') that would be much simpler:

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event

Base = declarative_base()

@event.listens_for(Column, before_parent_attach)
def attach(col, table, **kw):
if table.name in prefix_tables:
# the trick here is that col.key remains
# without the underscore
col.name = _ + col.name

prefix_tables = set()
class PrefixStuff(object):
# need to use a metaclass here because we have no event
# that will give you the __tablename__ + Language class
# before the Table is actually created
class __metaclass__(type(Base)):
def __init__(self, classname, bases, dict_):
prefix_tables.add(dict_.get('__tablename__'))
if classname == 'PrefixStuff':
return type.__init__(self, classname, bases, dict_)
else:
return type(Base).__init__(self, classname, bases, dict_)

class Language(PrefixStuff, Base):
__tablename__ = 'language'
language_id = Column(Integer, primary_key=True)
language = Column(String(5), unique=True, default='undef')

e = create_engine(sqlite://, echo=True)
Base.metadata.create_all(e)
sess = Session(e)

sess.add(Language(language='asdf'))
sess.commit()



On Jun 7, 2013, at 1:40 PM, Richard Gerd Kuesters rich...@humantech.com.br 
wrote:

 Thank you Mike!
 
 That brings me to another question:
 
 Let's say I have created a simple table (well, I have):
 
 class Language(Base):
 language_id = Column(Integer, Sequence('language_id_seq', optional=True), 
 primary_key=True)
 language = Column(String(5), unique=True, default='undef')
 
 The problem is (using pdb):
 
 (Pdb) lang = Language(language='test')
 (Pdb) lang
 Language(language='test')
 (Pdb) dir(lang)
 ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
 '__getattribute__', '__hash__', '__init__', '__mapper__', '__mapper_cls__', 
 '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 
 '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__table__', 
 '__tablename__', '__weakref__', '_cls_id', '_decl_class_registry', '_has', 
 '_language', '_language_id', '_sa_class_manager', '_sa_instance_state', 
 'id_', 'language', 'language_id', 'metadata', 't']
 (Pdb) session.add(lang)
 (Pdb) session.commit()
 (Pdb) lang2 = Language(language='foo')
 (Pdb) session.add(lang2)
 (Pdb) session.commit()
 *** IntegrityError: (IntegrityError) column language is not unique u'INSERT 
 INTO ht__language (language) VALUES (?)' ('undef',)
 (Pdb) session.rollback()
 (Pdb) session.query(Language).all()
 [Language(language='test')]
 (Pdb) lang2 = Language()
 (Pdb) lang2.language = 'foo'
 (Pdb) session.add(lang2)
 (Pdb) session.commit()
 *** IntegrityError: (IntegrityError) column language is not unique u'INSERT 
 INTO ht__language (language) VALUES (?)' ('undef',)
 (Pdb) session.rollback()
 (Pdb) lang2 = Language()
 (Pdb) lang2._language = 'foo'
 (Pdb) session.add(lang2)
 (Pdb) session.commit()
 (Pdb) session.query(Language).all()
 [Language(), Language(language='test')]
 
 If I change the Language class to this:
 
 class Language(Base):
 language_id = Column(Integer, Sequence('language_id_seq', optional=True), 
 primary_key=True)
 language = Column('language', String(5), unique=True, default='undef')
 
 The same happens. Curiously:
 
 (Pdb) session.query(Language).all()
 [Language(), Language(language='test')]
 (Pdb) map(lambda a: a._language, session.query(Language).all())
 [u'foo', u'undef']
 
 Is there a problem using this mapper configuration with declarative bases?
 
 Cheers,
 Richard.
 
 
 
 On 06/07/2013 11:46 AM, Michael Bayer wrote:
 
 On Jun 7, 2013, at 9:31 AM, Richard Gerd Kuesters rich...@humantech.com.br 
 wrote:
 
 Hi all!
 
 I'm refactoring a database schema but I need it to mantain reverse 
 compatibility with older versions of our software - using views.
 
 But, to avoid confusion to other developers, new tables have two 
 underscores as a prefix, like:
 
 
 class Base(object):
 
 @declared_attr
 def __tablename__(cls):
 return __%s % to_python_case(cls.__name__)
 
 
 Now I want to add column prefixes too. I know I can append to this Base 
 object:
 
 __mapper_args__ = dict(
 column_prefix='_'
 )
 
 But, when I inherit this new base on classes that I need to use 
 __mapper_args__, column names probably won't have prefixes. Any ideas, 
 perhaps an event listener to prepend the underscore into *all* column names?
 
 one idea is you can intercept how mapper() is called by declarative by 
 

Re: [sqlalchemy] Simple [?] question about column prefixes

2013-06-07 Thread Richard Gerd Kuesters
Woah, I may have wondered that when I thought on attaching an event, but 
yes I was thinking the opposite when using it like the underscores in 
the table name level.


I can't see how this was easier - lol - but it makes sense to me :)

Thanks Mike! This should get into the SA examples or recipes!

Best regards,
Richard.

On 06/07/2013 03:13 PM, Michael Bayer wrote:
OK, the prefix is on the mapped attribute name, not the column.  So 
Language(_language = 'foo').


Guess you're looking for the opposite, huh. This gets more weird 
but this should work, the main difficulty is limiting the columns 
being altered to just those within a certain class hierarchy, if you 
wanted to do it based on table.name.startswith('__') that would be 
much simpler:


from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event

Base = declarative_base()

@event.listens_for(Column, before_parent_attach)
def attach(col, table, **kw):
if table.name in prefix_tables:
# the trick here is that col.key remains
# without the underscore
col.name = _ + col.name

prefix_tables = set()
class PrefixStuff(object):
# need to use a metaclass here because we have no event
# that will give you the __tablename__ + Language class
# before the Table is actually created
class __metaclass__(type(Base)):
def __init__(self, classname, bases, dict_):
prefix_tables.add(dict_.get('__tablename__'))
if classname == 'PrefixStuff':
return type.__init__(self, classname, bases, dict_)
else:
return type(Base).__init__(self, classname, bases, dict_)

class Language(PrefixStuff, Base):
__tablename__ = 'language'
language_id = Column(Integer, primary_key=True)
language = Column(String(5), unique=True, default='undef')

e = create_engine(sqlite://, echo=True)
Base.metadata.create_all(e)
sess = Session(e)

sess.add(Language(language='asdf'))
sess.commit()



On Jun 7, 2013, at 1:40 PM, Richard Gerd Kuesters 
rich...@humantech.com.br mailto:rich...@humantech.com.br wrote:



Thank you Mike!

That brings me to another question:

Let's say I have created a simple table (well, I have):

class Language(Base):
language_id = Column(Integer, Sequence('language_id_seq', 
optional=True), primary_key=True)

language = Column(String(5), unique=True, default='undef')

The problem is (using pdb):

(Pdb) lang = Language(language='test')
(Pdb) lang
Language(language='test')
(Pdb) dir(lang)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__mapper__', 
'__mapper_cls__', '__module__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__table__', '__tablename__', '__weakref__', 
'_cls_id', '_decl_class_registry', '_has', '_language', 
'_language_id', '_sa_class_manager', '_sa_instance_state', 'id_', 
'language', 'language_id', 'metadata', 't']

(Pdb) session.add(lang)
(Pdb) session.commit()
(Pdb) lang2 = Language(language='foo')
(Pdb) session.add(lang2)
(Pdb) session.commit()
*** IntegrityError: (IntegrityError) column language is not unique 
u'INSERT INTO ht__language (language) VALUES (?)' ('undef',)

(Pdb) session.rollback()
(Pdb) session.query(Language).all()
[Language(language='test')]
(Pdb) lang2 = Language()
(Pdb) lang2.language = 'foo'
(Pdb) session.add(lang2)
(Pdb) session.commit()
*** IntegrityError: (IntegrityError) column language is not unique 
u'INSERT INTO ht__language (language) VALUES (?)' ('undef',)

(Pdb) session.rollback()
(Pdb) lang2 = Language()
(Pdb) lang2._language = 'foo'
(Pdb) session.add(lang2)
(Pdb) session.commit()
(Pdb) session.query(Language).all()
[Language(), Language(language='test')]

If I change the Language class to this:

class Language(Base):
language_id = Column(Integer, Sequence('language_id_seq', 
optional=True), primary_key=True)
language = Column('language', String(5), unique=True, 
default='undef')


The same happens. Curiously:

(Pdb) session.query(Language).all()
[Language(), Language(language='test')]
(Pdb) map(lambda a: a._language, session.query(Language).all())
[u'foo', u'undef']

Is there a problem using this mapper configuration with declarative 
bases?


Cheers,
Richard.



On 06/07/2013 11:46 AM, Michael Bayer wrote:


On Jun 7, 2013, at 9:31 AM, Richard Gerd Kuesters 
rich...@humantech.com.br mailto:rich...@humantech.com.br wrote:



Hi all!

I'm refactoring a database schema but I need it to mantain reverse 
compatibility with older versions of our software - using views.


But, to avoid confusion to other developers, new tables have two 
underscores as a prefix, like:



class Base(object):

@declared_attr
def __tablename__(cls):
return __%s % to_python_case(cls.__name__)


Now I want to add column prefixes too. I know I can append to this 
Base object:


   

Re: [sqlalchemy] Feature suggestion: fake ForeignKeyConstraints to simplify joins

2013-06-07 Thread Charlie Clark

Am 07.06.2013, 00:05 Uhr, schrieb Michael Bayer mike...@zzzcomputing.com:

can you show me the alternate design you have in mind?  I'm not sure  
what normalize to favorites with strict 1:1 looks like.


this is all just my own curiosity.   the issue at hand is something  
different.


Well, I guess I asked for it. Pseudo-tables

things (
thing_id SERIAL PRIMARY KEY
)

groups (
group_id SERIAL PRIMARY KEY
)

groups_things(
thing_id INTEGER FOREIGN KEY REFERENCES (things.thing_id),
group_id INTEGER FOREIGN KEY REFERENCES (groups.group_id)
)

favourites (I'm a limey) are just another relation.

favourites(
thing_id INTEGER PRIMARY KEY FOREIGN KEY REFERENCES (things.thing_id),
group_id INTEGER FOREIGN KEY REFERENCES (groups.group_id)
)

Depending on how you look at it, favourites are just another relation and  
could have additional attributes like colour, or simply behave like a  
sub-class of groups.


Am I missing something big in the original question as to why this isn't a  
reasonable solution?


Charlie
--
Charlie Clark
Managing Director
Clark Consulting  Research
German Office
Kronenstr. 27a
Düsseldorf
D- 40217
Tel: +49-211-600-3657
Mobile: +49-178-782-6226

--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Feature suggestion: fake ForeignKeyConstraints to simplify joins

2013-06-07 Thread Charlie Clark

Am 07.06.2013, 01:13 Uhr, schrieb Andy aml...@gmail.com:


I may be misunderstanding the question, but the reason that having a
favorite is optional is because I'm using mysql and mysql doesn't  
supported deferred constraints.


Oh, I feel your pain! But you are using an engine that at leasts pretends  
to support foreign key constraints. If not, book yourself in at the next  
asylum!



So if favorite were NOT NULL, then there would  be
no way to create the thing.


Which is why it should be a relation all of its own. I've a sneaking  
suspicion that I'm being incredibly dense and missing something obvious.


Charlie
--
Charlie Clark
Managing Director
Clark Consulting  Research
German Office
Kronenstr. 27a
Düsseldorf
D- 40217
Tel: +49-211-600-3657
Mobile: +49-178-782-6226

--
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




[sqlalchemy] My mapped tables are missing insert, update methods

2013-06-07 Thread Michael Nachtigal
After reading the documentation, I am under the impression that my mapped 
tables should have the methods insert() and update(). For example, see here:

http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html?highlight=update#sqlalchemy.schema.Table.update

But my mapped tables don't have those methods; why might that be?

 User
class 'blah.models.User'
 User.insert
Traceback (most recent call last):
  File stdin, line 1, in module
AttributeError: type object 'User' has no attribute 'insert'
 User.update
Traceback (most recent call last):
  File stdin, line 1, in module
AttributeError: type object 'User' has no attribute 'update'

Thanks,
Mike

-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] My mapped tables are missing insert, update methods

2013-06-07 Thread Josh Kuhn
Your User class is mapped to a Table. It's not the Table itself. To get the
update method, you need to access User.__table__.update


On Fri, Jun 7, 2013 at 4:12 PM, Michael Nachtigal 
michael.nachti...@catalinamarketing.com wrote:

  After reading the documentation, I am under the impression that my
 mapped tables should have the methods insert() and update(). For example,
 see here:


 http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html?highlight=update#sqlalchemy.schema.Table.update

 But my mapped tables don't have those methods; why might that be?

  User
 class 'blah.models.User'
  User.insert
 Traceback (most recent call last):
   File stdin, line 1, in module
 AttributeError: type object 'User' has no attribute 'insert'
  User.update
 Traceback (most recent call last):
   File stdin, line 1, in module
 AttributeError: type object 'User' has no attribute 'update'

 Thanks,
 Mike

 --
 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?hl=en.
 For more options, visit https://groups.google.com/groups/opt_out.




-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: [sqlalchemy] Connect to SQL Server (with pyodbc) getting error: sqlalchemy.exc.DBAPIError: (Error) ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default dri

2013-06-07 Thread Victor Reichert
Thank you!
 
That got me going.
 
For what it's worth, I was using python 3.3 and trying to generate a custom 
connection string wtih the following command:
 
import urllib
string = urllib.quote_plus('DRIVER={SQL 
Server};Server=Server;Database=DB;Trusted_Connection=Yes')
conn = pyodbc.PyODBCConnector()
url = make_url('mssql+pyodbc://?odbc_connect='+string)
connect_args = conn.create_connect_args(url)
print(connect_args)
 
Which generated:
 
 
AttributeError: 'module' object has no attribute 'quote_plus'
I swtiched to python 2.7 and it worked fine.  If the above issue is a 
general problem in python 3, It might be worth noting the the documentation 
example will not work in that version.
 
I'm getting the feeling that python3 is not well supported yet.  
 
Thank you again for your help,
 
~Victor

On Thursday, June 6, 2013 12:38:03 PM UTC-5, Michael Bayer wrote:

 I will show you a short program that you can use to experiment with the 
 Pyodbc connector - the purpose of this program is to illustrate what 
 SQLAlchemy will send to pyodbc.connect(): 

  from sqlalchemy.connectors import pyodbc
 from sqlalchemy.engine.url import make_url

 conn = pyodbc.PyODBCConnector()
 url = make_url('mssql+pyodbc://DSN=py_test; Trusted_Connection=Yes')
 connect_args = conn.create_connect_args(url)
 print(connect_args)

 This returns:

 [['dsn=DSN=py_test; Trusted_Connection=Yes;Trusted_Connection=Yes'], {}]

 where you can see there's an extra DSN= in there.  

 There's a large number of connection examples for Pyodbc here:  
 http://docs.sqlalchemy.org/en/rel_0_8/dialects/mssql.html#additional-connection-examples

 You can see, that for standard TrustedConnection, you only need the dsn 
 name:

 create_engine('mssql+pyodbc://mydsn')

 which our test script shows the arguments as:

 [['dsn=mydsn;Trusted_Connection=Yes'], {}]

 looks good to me, so good luck !







  On Jun 5, 2013, at 9:47 PM, Victor Reichert vfr...@gmail.comjavascript: 
 wrote:

  Hello World!
  
 This is my first foray into python and SQL Alchemy, and I'm spinning my 
 wheels.  I'm running the code below and am able to connect to my DB and 
 query data without error.
  
 import pyodbc
 cnxn = pyodbc.connect('DSN=py_test; Trusted_Connection=Yes')
  
 However, when I try 

 import sqlalchemy
 engine = sqlalchemy.create_engine('mssql+pyodbc://DSN=py_test; 
 Trusted_Connection=Yes')
 result = engine.execute(SELECT * FROM dbo.test_table)
 I receive the following error, I am running python 3.3 on 32 bit Windows 7 
 Enterprise
  
 Traceback (most recent call last):
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 757, in 
 _do_get
 return self._pool.get(wait, self._timeout)
   File C:\Python33\lib\site-packages\sqlalchemy\util\queue.py, line 166, 
 in get
 raise Empty
 sqlalchemy.util.queue.Empty
 During handling of the above exception, another exception occurred:
 Traceback (most recent call last):
   File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, 
 line 80, in connect
 return dialect.connect(*cargs, **cparams)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\default.py, line 
 285, in connect
 return self.dbapi.connect(*cargs, **cparams)
 pyodbc.Error: ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data 
 source name not found and no default driver specified (0) 
 (SQLDriverConnect)')
 The above exception was the direct cause of the following exception:
 Traceback (most recent call last):
   File 
 C:\Users\V114804\workspace\Remetrica_Simulated_ILC_WW_AP_20130520_ELT\Src\Test_DB_Connection.py,
  
 line 11, in module
 result = engine.execute(SELECT * FROM dbo.test_table)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 
 1613, in execute
 connection = self.contextual_connect(close_with_result=True)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 
 1661, in contextual_connect
 self.pool.connect(),
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 272, in 
 connect
 return _ConnectionFairy(self).checkout()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 425, in 
 __init__
 rec = self._connection_record = pool._do_get()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 777, in 
 _do_get
 con = self._create_connection()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 225, in 
 _create_connection
 return _ConnectionRecord(self)
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 318, in 
 __init__
 self.connection = self.__connect()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 368, in 
 __connect
 connection = self.__pool._creator()
   File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, 
 line 87, in connect
 ) from e
 sqlalchemy.exc.DBAPIError: (Error) ('IM002', '[IM002] [Microsoft][ODBC 
 Driver Manager] Data source name not found and no default driver specified 
 (0) (SQLDriverConnect)') None None
  
 I have also 

Re: [sqlalchemy] Connect to SQL Server (with pyodbc) getting error: sqlalchemy.exc.DBAPIError: (Error) ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default dri

2013-06-07 Thread Michael Bayer

On Jun 7, 2013, at 6:11 PM, Victor Reichert vfr...@gmail.com wrote:

 Thank you!
  
 That got me going.
  
 For what it's worth, I was using python 3.3 and trying to generate a custom 
 connection string wtih the following command:
  
 import urllib
 string = urllib.quote_plus('DRIVER={SQL 
 Server};Server=Server;Database=DB;Trusted_Connection=Yes')
 conn = pyodbc.PyODBCConnector()
 url = make_url('mssql+pyodbc://?odbc_connect='+string)
 connect_args = conn.create_connect_args(url)
 print(connect_args)
  
 Which generated:
  
 AttributeError: 'module' object has no attribute 'quote_plus'
 
 I swtiched to python 2.7 and it worked fine.  If the above issue is a general 
 problem in python 3, It might be worth noting the the documentation example 
 will not work in that version.
  
 I'm getting the feeling that python3 is not well supported yet. 

not for pyodbc in 0.8, but in 0.9 (git master) it's working pretty well (no 
2to3 step either).




  
 Thank you again for your help,
  
 ~Victor
 
 On Thursday, June 6, 2013 12:38:03 PM UTC-5, Michael Bayer wrote:
 I will show you a short program that you can use to experiment with the 
 Pyodbc connector - the purpose of this program is to illustrate what 
 SQLAlchemy will send to pyodbc.connect():
 
 from sqlalchemy.connectors import pyodbc
 from sqlalchemy.engine.url import make_url
 
 conn = pyodbc.PyODBCConnector()
 url = make_url('mssql+pyodbc://DSN=py_test; Trusted_Connection=Yes')
 connect_args = conn.create_connect_args(url)
 print(connect_args)
 
 This returns:
 
 [['dsn=DSN=py_test; Trusted_Connection=Yes;Trusted_Connection=Yes'], {}]
 
 where you can see there's an extra DSN= in there.  
 
 There's a large number of connection examples for Pyodbc here:  
 http://docs.sqlalchemy.org/en/rel_0_8/dialects/mssql.html#additional-connection-examples
 
 You can see, that for standard TrustedConnection, you only need the dsn 
 name:
 
 create_engine('mssql+pyodbc://mydsn')
 
 which our test script shows the arguments as:
 
 [['dsn=mydsn;Trusted_Connection=Yes'], {}]
 
 looks good to me, so good luck !
 
 
 
 
 
 
 
 On Jun 5, 2013, at 9:47 PM, Victor Reichert vfr...@gmail.com wrote:
 
 Hello World!
  
 This is my first foray into python and SQL Alchemy, and I'm spinning my 
 wheels.  I'm running the code below and am able to connect to my DB and 
 query data without error.
  
 import pyodbc
 cnxn = pyodbc.connect('DSN=py_test; Trusted_Connection=Yes')
  
 However, when I try
 
 import sqlalchemy
 engine = sqlalchemy.create_engine('mssql+pyodbc://DSN=py_test; 
 Trusted_Connection=Yes')
 result = engine.execute(SELECT * FROM dbo.test_table)
 I receive the following error, I am running python 3.3 on 32 bit Windows 7 
 Enterprise
  
 Traceback (most recent call last):
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 757, in 
 _do_get
 return self._pool.get(wait, self._timeout)
   File C:\Python33\lib\site-packages\sqlalchemy\util\queue.py, line 166, 
 in get
 raise Empty
 sqlalchemy.util.queue.Empty
 During handling of the above exception, another exception occurred:
 Traceback (most recent call last):
   File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, line 
 80, in connect
 return dialect.connect(*cargs, **cparams)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\default.py, line 
 285, in connect
 return self.dbapi.connect(*cargs, **cparams)
 pyodbc.Error: ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data 
 source name not found and no default driver specified (0) 
 (SQLDriverConnect)')
 The above exception was the direct cause of the following exception:
 Traceback (most recent call last):
   File 
 C:\Users\V114804\workspace\Remetrica_Simulated_ILC_WW_AP_20130520_ELT\Src\Test_DB_Connection.py,
  line 11, in module
 result = engine.execute(SELECT * FROM dbo.test_table)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 1613, 
 in execute
 connection = self.contextual_connect(close_with_result=True)
   File C:\Python33\lib\site-packages\sqlalchemy\engine\base.py, line 1661, 
 in contextual_connect
 self.pool.connect(),
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 272, in 
 connect
 return _ConnectionFairy(self).checkout()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 425, in 
 __init__
 rec = self._connection_record = pool._do_get()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 777, in 
 _do_get
 con = self._create_connection()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 225, in 
 _create_connection
 return _ConnectionRecord(self)
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 318, in 
 __init__
 self.connection = self.__connect()
   File C:\Python33\lib\site-packages\sqlalchemy\pool.py, line 368, in 
 __connect
 connection = self.__pool._creator()
   File C:\Python33\lib\site-packages\sqlalchemy\engine\strategies.py, line 
 87, in connect
 ) from e
 

[sqlalchemy] AssociationProxy's behavior with == None seems unintuitive

2013-06-07 Thread Greg Yang
Right now a filter clause AssociationProxy == None 

Consider the following code:

from sqlalchemy.engine import create_engine
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer, String

Base = declarative_base()

class A(Base):
__tablename__ = 'table_a'
id = Column(Integer, primary_key=True)
color = Column(String)
def __init__(self, color):
self.color = color

class B(Base):
__tablename__ = 'table_b'
id = Column(Integer, primary_key=True)
a_id = Column(Integer, ForeignKey('table_a.id'))
a_re = relationship('A', backref='b_re')
a_color = association_proxy('a_re', 'color')


if __name__ == '__main__':
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(engine)
session = Session()
Base.metadata.create_all(engine)

b1 = B()
b2 = B()
b3 = B()

b1.a_color = 'blue'
session.add_all([b1, b2, b3])

q = session.query(B).filter(B.a_color == None).all()
p = session.query(B).filter(B.a_color != None).all()

assert q == []
assert set(p) == set([b1, b2, b3])

I find it surprising that, when only b1 really has a color string through 
B.a_color, filtering for B.a_color == None doesn't return b2 and b3, and 
filtering for B.a_color != None returns b2 and b3 at all. The latter is 
especially unintuitive.

Now I know what's going on:

 print B.a_color == None
EXISTS (SELECT 1 
FROM table_a 
WHERE table_a.id = table_b.a_id AND table_a.color IS NULL)
 print B.a_color != None
NOT (EXISTS (SELECT 1 
FROM table_a 
WHERE table_a.id = table_b.a_id AND table_a.color IS NULL))

The == clause requires that the relationship a_re has a valid target in the 
first place before checking for a_re.color IS NULL, and the != is just the 
negation of that. I understand that this is the desired action when the 
right side is some non-null value like blue, but in this case it should 
be implemented along the lines of

 print B.a_color == None
table_b.a_id IS NULL 
OR
EXISTS (SELECT 1 
FROM table_a 
WHERE table_a.id = table_b.a_id AND table_a.color IS NULL)
 print B.a_color != None
table_b.a_id IS NOT NULL
AND
NOT (EXISTS (SELECT 1 
FROM table_a 
WHERE table_a.id = table_b.a_id AND table_a.color IS NULL))

On a similar note, is there a way to get a_re.has() or equivalent through 
only a_color? This can be important when a_re is supposed to be a private 
variable, and only the string a_color is exposed. I originally thought that 
!= None would do the trick but that doesn't work, as I've shown here.


-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.