[sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Hi,
I have a model similar to the following:

class Employee(Base):
__tablename__ = t_employee

id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
primary_key=True, nullable=False)
first_name = sa.Column(sa.String(30))
last_name = sa.Column(sa.String(30))
phone_number = sa.Column(sa.String(30))

_jobs = sa.orm.relationship(EmployeeJob, lazy=joined, cascade=all, 
delete, delete-orphan)

@property
def name(self):
return self.first_name + (  + self.last_name if 
len(self.last_name or )  0 else )

@property
def jobs(self):
return [item.job_id for item in sorted(self._jobs, 
key=attrgetter('id'))]

@jobs.setter
def jobs(self, value):
self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)]

class EmployeeJob(Base):
id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % __tablename__), 
primary_key=True, nullable=False)
employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id', 
ondelete=CASCADE), nullable=False)
job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id', 
ondelete=CASCADE), nullable=False)


Now, I'm trying to write a simple query that will fetch all employees with 
their jobs.
As I understand, I need to use joinedload so that the list of jobs will be 
eagerly loaded but I can't understand how to do it.

I tried the following:
session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs))

but it doesn't work.

Just to clarify, I want to load some of the columns, not all of them, and 
I'm expecting to get the list of jobs for each employee (hopefully like the 
getter produces them)

session.query(Employee) does fetch the required information but it selects 
some unneeded columns

Also, how do I select the name property?

Thanks,
Ofir

-- 
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.


Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Simon King
On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas herz...@gmail.com wrote:
 Hi,
 I have a model similar to the following:

 class Employee(Base):
 __tablename__ = t_employee

 id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__),
 primary_key=True, nullable=False)
 first_name = sa.Column(sa.String(30))
 last_name = sa.Column(sa.String(30))
 phone_number = sa.Column(sa.String(30))

 _jobs = sa.orm.relationship(EmployeeJob, lazy=joined, cascade=all,
 delete, delete-orphan)

 @property
 def name(self):
 return self.first_name + (  + self.last_name if len(self.last_name
 or )  0 else )

 @property
 def jobs(self):
 return [item.job_id for item in sorted(self._jobs,
 key=attrgetter('id'))]

 @jobs.setter
 def jobs(self, value):
 self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)]

 class EmployeeJob(Base):
 id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % __tablename__),
 primary_key=True, nullable=False)
 employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id',
 ondelete=CASCADE), nullable=False)
 job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id',
 ondelete=CASCADE), nullable=False)


 Now, I'm trying to write a simple query that will fetch all employees with
 their jobs.
 As I understand, I need to use joinedload so that the list of jobs will be
 eagerly loaded but I can't understand how to do it.

 I tried the following:
 session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs))

 but it doesn't work.

 Just to clarify, I want to load some of the columns, not all of them, and
 I'm expecting to get the list of jobs for each employee (hopefully like the
 getter produces them)

 session.query(Employee) does fetch the required information but it selects
 some unneeded columns

 Also, how do I select the name property?

 Thanks,
 Ofir


Eager loading means that when you have an instance of Employee, and
you access its 'jobs' property, no SQL is emitted because the data is
already available. This implies that you have to query for the
Employee class, not just one of its columns (otherwise you wouldn't
have an instance from which to access the jobs property)

If you don't want to load all the Employee columns, you can defer them:

  
http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-column-loading

Hope that helps,

Simon

-- 
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.


[sqlalchemy] Re: Selecting columns from multiple table join in SQLAlchemy Core

2014-09-04 Thread Jonathan Vanasco
the first thing I noticed, is that you're referencing the idea of the 
tables in two separate ways : `self.execs` and `execs`

are they the same python object?

-- 
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.


Re: [sqlalchemy] Selecting columns from multiple table join in SQLAlchemy Core

2014-09-04 Thread Michael Bayer

I think the join.select(columns, whereclasue) part here is wrong, the select() 
method unfortunately does not have that calling signature (I wish it did, but 
there's a lot of legacy there).

You can get the columns you want more explicitly, select([c1, c2, c3, 
..]).select_from(my_join).

The exception raised here is probably sqlalchemy being surprised by the list of 
columns being sent (the error message would do better to report on what it 
sees).

On Sep 4, 2014, at 1:11 AM, apoorv.x.kulshres...@barclays.com wrote:

 Hi All,
  
 I am joining 3 tables in SQLAlchemy Core and selecting all columns as follows:
  
 rows = self.db.execute(self.execs.join(
  self.orders.join(self.instruments)
  ).select(whereClause)).reduce_columns())
  
 It works well but if I want to select a subset of columns:
  
 reqdCols = [order.c.id, exec.c.last_modified, instruments.type]
 rows = self.db.execute(self.execs.join(
  self.orders.join(self.instruments)
   ).select(reqdCols, whereClause)).reduce_columns())
 It doesn't works and gives following error:
  
 Traceback (most recent call last):
   File stdin, line 1, in module
   File 
 /apps/qtdist/pkgs/pub/cpython/python-2.7.6/lib/python2.7/site-packages/sqlalchemy/sql/selectable.py,
  line 807, in select
 return Select(collist, whereclause, from_obj=[self], **kwargs)
   File 
 /apps/qtdist/pkgs/pub/cpython/python-2.7.6/lib/python2.7/site-packages/sqlalchemy/sql/selectable.py,
  line 2219, in __init__
 whereclause).self_group(against=operators._asbool)
   File 
 /apps/qtdist/pkgs/pub/cpython/python-2.7.6/lib/python2.7/site-packages/sqlalchemy/sql/elements.py,
  line 3438, in _literal_as_text
 SQL expression object or string expected.
 sqlalchemy.exc.ArgumentError: SQL expression object or string expected.
  
 Alternative would be to use select instead of Join.select and make it 
 implicit join with where clauses:
  
 joinConditions = (orders.c.colx == execs.colx)  (execs.c.coly == 
 instruments.c.coly)
 select(reqdCols).where(and_(whereClause, joinConditions)
  
 But I would prefer explicit join over implicit for performance reasons. Is 
 there any way to select subset of columns using explicit joins?
  
 Regards,
 Apoorv
  
 PS: I have post the same in Stack Overflow Question: 
 http://stackoverflow.com/questions/25656935/selecting-columns-from-mulitple-table-join-in-sqlalchemy-core#
 ___
 
 This message is for information purposes only, it is not a recommendation, 
 advice, offer or solicitation to buy or sell a product or service nor an 
 official confirmation of any transaction. It is directed at persons who are 
 professionals and is not intended for retail customer use. Intended for 
 recipient only. This message is subject to the terms at: 
 www.barclays.com/emaildisclaimer.
 
 For important disclosures, please see: 
 www.barclays.com/salesandtradingdisclaimer regarding market commentary from 
 Barclays Sales and/or Trading, who are active market participants; and in 
 respect of Barclays Research, including disclosures relating to specific 
 issuers, please seehttp://publicresearch.barclays.com.
 
 ___
 
 
 -- 
 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 tosqlalchemy+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.

-- 
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.


Re: [sqlalchemy] Wrapping polymorphic model for Pyramid traversal

2014-09-04 Thread Michael Bayer
this is probably more of a Pyramid question.

I'm pretty allergic to traversal myself :)


On Sep 3, 2014, at 2:58 PM, Milo Toor milo.t...@gmail.com wrote:

 Hi.
 
 I am trying to wrap a polymorphic model so that it can act as a traversal 
 node in a Pyramid application:
 
 from sqlalchemy import Column, Integer, String, create_engine
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy.ext.declarative import declarative_base
 
 
 Base = declarative_base()
 engine = create_engine('sqlite:///:memory:', echo=True)
 Session = sessionmaker(bind=engine)
 
 
 # This is the class we wish to wrap
 class Employee(Base):
 __tablename__ = 'employee'
 id = Column(Integer, primary_key=True)
 name = Column(String(50))
 type = Column(String(20))
 
 
 __mapper_args__ = {
 'polymorphic_on': type,
 'polymorphic_identity': 'employee'
 }
 
 
 
 class Manager(Employee):
 __mapper_args__ = {
 'polymorphic_identity': 'manager'
 }
 
 
 
 class Engineer(Employee):
 __mapper_args__ = {
 'polymorphic_identity': 'engineer'
 }
 
 
 
 class EmployeeInTraversal(Employee):
 
 Wraps the Employee class. This is to keep our models and our application
 logic decoupled.
 
 def __getitem__(self, key):
 
 Make the employee behave like a traversal node.
 
 :param key:
 The traversal key. If asked for tasks return the appropriate root
 factory
 
 if key == 'tasks':
 return 'TasksRootFactory()'
 raise KeyError
 
 
 # Create the tables
 Base.metadata.create_all(engine)
 
 
 # Create both a Manager and an Engineer
 manager = Manager(name='Taylor')
 engineer = Engineer(name='Sam')
 
 
 session = Session()
 session.add_all([manager, engineer])
 session.commit()
 
 
 # somewhere a request is made for /employee/1/tasks...
 
 
 # Query for the engineer, somewhere in the EmployeeRootFactory
 wrapped_engineer = session.query(EmployeeInTraversal).get(1)
 
 
 # Traversal doing its thing. Here lies the trouble.
 engineer_tasks = wrapped_engineer['tasks']
 
 The last line of this code throws a TypeError with the message 'NoneType' 
 object has no attribute '__getitem__'. Nothing is turned up by the query to 
 EmployeeInTraversal. If the query is instead made with the Employee class, we 
 get a similar TypeError: 'Manager' object has no attribute '__getitem__'. So 
 in other words, querying EmployeeInTraversal returns nothing, but querying 
 Employee returns the object, although unwrapped.
 
 The reason for this, near as I can tell, is that the EmployeeInTraversal 
 class is being interpreted as a subtype of Employee rather than as a wrapper 
 for the class. I attribute this to the polymorphic nature of the Employee 
 class, but at this point I'm really just banging my head against the wall. We 
 would very much like to keep our models and application logic separate, and 
 not embed traversal logic in the schema classes... Is there any way to wrap a 
 polymorphic class without the wrapper being interpreted as a sub-type?
 
 -- 
 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.

-- 
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.


Re: [sqlalchemy] Query filter NameError issue

2014-09-04 Thread Michael Bayer
Hi Gilles -

if you've imported models, you need to refer to Series as models.Series, 
unless you imported Series individually which seems to not be the case.

The second part of things, if you call query.filter(), you get a new Query 
object back, just like with most Query methods, until you do one of the 
following:   iterate it, e.g. for  x in query:, or call one of .all(), 
.one(), or .first().



On Aug 30, 2014, at 11:12 AM, Gilles Coulais gilles.coul...@gmail.com wrote:

 Hi all,
 
 I'm starting to have a look at sqlalchemy and Flask and have a problem I 
 can't figure out. I have a set of models and am trying to play with the 
 corresponding database in a python console. Here is my models file: 
 http://snipurl.com/297pxcw
 
 The following query will execute as expected and return a list of Series 
 objects, as present in the database
 from book_catalog import models, db
 series = models.Series.query.all()
 for serie in series:
 print serie.id, serie.name
 1 Nikopol
 
 But executing the following query will return an error:
 nikopol = models.Series.query.filter(Series.name == 'Nikopol')
 Traceback (most recent call last):
   File stdin, line 1, in module
 NameError: name 'Series' is not defined
 
 I tried the following, which is executing, but returning a Query object (not 
 exactly what I'm trying to do ;) )
 nikopol = models.Series.query.filter(models.Series.name == 'Nikopol')
 print nikopol
 SELECT series.id AS series_id, series.name AS series_name 
 FROM series 
 WHERE series.name = :name_1
 
 Can anyone explain what I'm doing wrong here? I'm using SqlAlchemy 0.9.7
 
 sqlalchemy.__version__
 '0.9.7'
 
 Thanks a lot in advance.
 
 Gilles
 
 -- 
 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.

-- 
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.


[sqlalchemy] adding columns dynamically to an ORM class ?

2014-09-04 Thread Jonathan Vanasco
is it possible to add a column to an ORM class after the engine and mapper 
have initialized?

I have a maintenance/migration script that needs a new column on the table 
for the duration of the script.  

For a variety of reasons, I need to avoid altering the actual model.

I found `append_column`, but that works on `model.TableClass.__table__`.  

-- 
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.


[sqlalchemy] Re: adding columns dynamically to an ORM class ?

2014-09-04 Thread Jonathan Vanasco
nevermind, i overthought this.  

apparently this is all i needed:

   model.TableClass.temp_column = sqlalchemy.Column(sqlalchemy.Integer)

-- 
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.


Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Thanks Simon,
I've tried the following:

session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only(
'id', 'first_name')).all()

which according to the documentation (
http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loading-with-multiple-entities)
 
should work, but it throws an exception (ArgumentError: mapper option 
expects string key or list of attributes)

Can you please provide an example?

Please notice that I'm trying to load only some properties of Employee 
(including one relationship) while this behavior should not be the default 
behavior (meaning that I don't want the defer the columns at model level)


On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:

 On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com 
 javascript: wrote: 
  Hi, 
  I have a model similar to the following: 
  
  class Employee(Base): 
  __tablename__ = t_employee 
  
  id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  first_name = sa.Column(sa.String(30)) 
  last_name = sa.Column(sa.String(30)) 
  phone_number = sa.Column(sa.String(30)) 
  
  _jobs = sa.orm.relationship(EmployeeJob, lazy=joined, 
 cascade=all, 
  delete, delete-orphan) 
  
  @property 
  def name(self): 
  return self.first_name + (  + self.last_name if 
 len(self.last_name 
  or )  0 else ) 
  
  @property 
  def jobs(self): 
  return [item.job_id for item in sorted(self._jobs, 
  key=attrgetter('id'))] 
  
  @jobs.setter 
  def jobs(self, value): 
  self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
  
  class EmployeeJob(Base): 
  id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % 
 __tablename__), 
  primary_key=True, nullable=False) 
  employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id', 

  ondelete=CASCADE), nullable=False) 
  job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id', 
  ondelete=CASCADE), nullable=False) 
  
  
  Now, I'm trying to write a simple query that will fetch all employees 
 with 
  their jobs. 
  As I understand, I need to use joinedload so that the list of jobs will 
 be 
  eagerly loaded but I can't understand how to do it. 
  
  I tried the following: 
  session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs)) 
  
  but it doesn't work. 
  
  Just to clarify, I want to load some of the columns, not all of them, 
 and 
  I'm expecting to get the list of jobs for each employee (hopefully like 
 the 
  getter produces them) 
  
  session.query(Employee) does fetch the required information but it 
 selects 
  some unneeded columns 
  
  Also, how do I select the name property? 
  
  Thanks, 
  Ofir 
  

 Eager loading means that when you have an instance of Employee, and 
 you access its 'jobs' property, no SQL is emitted because the data is 
 already available. This implies that you have to query for the 
 Employee class, not just one of its columns (otherwise you wouldn't 
 have an instance from which to access the jobs property) 

 If you don't want to load all the Employee columns, you can defer them: 

   
 http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-column-loading
  

 Hope that helps, 

 Simon 


-- 
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.


Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Jonathan Vanasco
load_only indicates the columns in Employee.jobs that you want to load.

'first_name' is located on Employee, not EmployeeJob

-- 
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.


Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 12:28 PM, Ofir Herzas herz...@gmail.com wrote:

 Thanks Simon,
 I've tried the following:
 
 session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('id',
  'first_name')).all()
 
 which according to the documentation 
 (http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loading-with-multiple-entities)
  should work, but it throws an exception (ArgumentError: mapper option 
 expects string key or list of attributes)
 
 Can you please provide an example?

check your SQLAlchemy version, I cannot reproduce that issue:

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

Base = declarative_base()

class Employee(Base):
__tablename__ = 'employee'

id = Column(Integer, primary_key=True)
jobs = relationship(Job)

class Job(Base):
__tablename__ = 'job'

id = Column(Integer, primary_key=True)
employee_id = Column(Integer, ForeignKey('employee.id'))
first_name = Column(String)

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

session = Session(e)

session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
'first_name')).all()

output:

SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS 
job_1_first_name 
FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id = job_1.employee_id



 
 Please notice that I'm trying to load only some properties of Employee 
 (including one relationship) while this behavior should not be the default 
 behavior (meaning that I don't want the defer the columns at model level)
 
 
 On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:
 On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com wrote: 
  Hi, 
  I have a model similar to the following: 
  
  class Employee(Base): 
  __tablename__ = t_employee 
  
  id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  first_name = sa.Column(sa.String(30)) 
  last_name = sa.Column(sa.String(30)) 
  phone_number = sa.Column(sa.String(30)) 
  
  _jobs = sa.orm.relationship(EmployeeJob, lazy=joined, cascade=all, 
  delete, delete-orphan) 
  
  @property 
  def name(self): 
  return self.first_name + (  + self.last_name if 
  len(self.last_name 
  or )  0 else ) 
  
  @property 
  def jobs(self): 
  return [item.job_id for item in sorted(self._jobs, 
  key=attrgetter('id'))] 
  
  @jobs.setter 
  def jobs(self, value): 
  self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
  
  class EmployeeJob(Base): 
  id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id', 
  ondelete=CASCADE), nullable=False) 
  job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id', 
  ondelete=CASCADE), nullable=False) 
  
  
  Now, I'm trying to write a simple query that will fetch all employees with 
  their jobs. 
  As I understand, I need to use joinedload so that the list of jobs will be 
  eagerly loaded but I can't understand how to do it. 
  
  I tried the following: 
  session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs)) 
  
  but it doesn't work. 
  
  Just to clarify, I want to load some of the columns, not all of them, and 
  I'm expecting to get the list of jobs for each employee (hopefully like the 
  getter produces them) 
  
  session.query(Employee) does fetch the required information but it selects 
  some unneeded columns 
  
  Also, how do I select the name property? 
  
  Thanks, 
  Ofir 
  
 
 Eager loading means that when you have an instance of Employee, and 
 you access its 'jobs' property, no SQL is emitted because the data is 
 already available. This implies that you have to query for the 
 Employee class, not just one of its columns (otherwise you wouldn't 
 have an instance from which to access the jobs property) 
 
 If you don't want to load all the Employee columns, you can defer them: 
 
   
 http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-column-loading
  
 
 Hope that helps, 
 
 Simon 
 
 -- 
 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.

-- 
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 

RE: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Thanks Michael,

I'm using 0.9.7 and while your example did work, the following did not:

 

from sqlalchemy import *

from sqlalchemy.orm import *

from sqlalchemy.ext.declarative import declarative_base

 

Base = declarative_base()

 

class Employee(Base):

__tablename__ = 'employee'

 

id = Column(Integer, primary_key=True)

first_name = Column(String)

_jobs = relationship(EmployeeJob, lazy=joined)

 

@property

def jobs(self):

return [item.job_id for item in sorted(self._jobs,
key=attrgetter('id'))]

 

class EmployeeJob(Base):

__tablename__ = employee_job

 

id = Column(Integer, primary_key=True)

employee_id = Column(Integer, ForeignKey('employee.id'))

job_id = Column(Integer, ForeignKey('job.id'))

 

class Job(Base):

__tablename__ = 'job'

 

id = Column(Integer, primary_key=True)

name = Column(String)

 

e = create_engine(sqlite://, echo=True)

Base.metadata.create_all(e)

 

session = Session(e)

 

session.query(Employee).options(joinedload(Employee.jobs).load_only('id',
'first_name')).all()

 

 

Notice that the difference here is that I'm using a property decorator on
jobs, there is a link table (EmployeeJob), and I'm trying to load
information of Employee (first_name should be from there)

 

Thanks,

Ofir

 

From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On
Behalf Of Michael Bayer
Sent: Thursday, September 04, 2014 8:00 PM
To: sqlalchemy@googlegroups.com
Subject: Re: [sqlalchemy] selecting from a relationship

 

 

On Sep 4, 2014, at 12:28 PM, Ofir Herzas herz...@gmail.com wrote:





Thanks Simon,

I've tried the following:

 

session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('
id', 'first_name')).all()

 

which according to the documentation
(http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loadi
ng-with-multiple-entities) should work, but it throws an exception
(ArgumentError: mapper option expects string key or list of attributes)

 

Can you please provide an example?

 

check your SQLAlchemy version, I cannot reproduce that issue:

 

from sqlalchemy import *

from sqlalchemy.orm import *

from sqlalchemy.ext.declarative import declarative_base

 

Base = declarative_base()

 

class Employee(Base):

__tablename__ = 'employee'

 

id = Column(Integer, primary_key=True)

jobs = relationship(Job)

 

class Job(Base):

__tablename__ = 'job'

 

id = Column(Integer, primary_key=True)

employee_id = Column(Integer, ForeignKey('employee.id'))

first_name = Column(String)

 

e = create_engine(sqlite://, echo=True)

Base.metadata.create_all(e)

 

session = Session(e)

 

session.query(Employee).options(joinedload(Employee.jobs).load_only('id',
'first_name')).all()

 

output:

 

SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS
job_1_first_name 

FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id =
job_1.employee_id

 

 





 

Please notice that I'm trying to load only some properties of Employee
(including one relationship) while this behavior should not be the default
behavior (meaning that I don't want the defer the columns at model level)



On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:

On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com javascript:
 wrote: 
 Hi, 
 I have a model similar to the following: 
 
 class Employee(Base): 
 __tablename__ = t_employee 
 
 id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
 primary_key=True, nullable=False) 
 first_name = sa.Column(sa.String(30)) 
 last_name = sa.Column(sa.String(30)) 
 phone_number = sa.Column(sa.String(30)) 
 
 _jobs = sa.orm.relationship(EmployeeJob, lazy=joined,
cascade=all, 
 delete, delete-orphan) 
 
 @property 
 def name(self): 
 return self.first_name + (  + self.last_name if
len(self.last_name 
 or )  0 else ) 
 
 @property 
 def jobs(self): 
 return [item.job_id for item in sorted(self._jobs, 
 key=attrgetter('id'))] 
 
 @jobs.setter 
 def jobs(self, value): 
 self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
 
 class EmployeeJob(Base): 
 id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' %
__tablename__), 
 primary_key=True, nullable=False) 
 employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id
http://t_employee.id/ ', 
 ondelete=CASCADE), nullable=False) 
 job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id
http://t_job.id/ ', 
 ondelete=CASCADE), nullable=False) 
 
 
 Now, I'm trying to write a simple query that will fetch all employees with

 their jobs. 
 As I understand, I need to use joinedload so that the list of jobs will be

 eagerly loaded but I can't understand how to do it. 
 
 I tried the following: 
 session.query(Employee.id).options(sa.orm.joinedload(Employee.jobs)) 
 
 but it doesn't work. 
 
 Just to clarify, I want to 

Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 1:32 PM, Ofir Herzas herz...@gmail.com wrote:

 Thanks Michael,
 I'm using 0.9.7 and while your example did work, the following did not:

Ok that's not a relationship().  joinedload() only works with relationships.




  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 first_name = Column(String)
 _jobs = relationship(EmployeeJob, lazy=joined)
  
 @property
 def jobs(self):
 return [item.job_id for item in sorted(self._jobs, 
 key=attrgetter('id'))]
  
 class EmployeeJob(Base):
 __tablename__ = employee_job
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 job_id = Column(Integer, ForeignKey('job.id'))
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
 'first_name')).all()
  
  
 Notice that the difference here is that I'm using a property decorator on 
 jobs, there is a link table (EmployeeJob), and I'm trying to load information 
 of Employee (first_name should be from there)
  
 Thanks,
 Ofir
  
 From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On 
 Behalf Of Michael Bayer
 Sent: Thursday, September 04, 2014 8:00 PM
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] selecting from a relationship
  
  
 On Sep 4, 2014, at 12:28 PM, Ofir Herzas herz...@gmail.com wrote:
 
 
 Thanks Simon,
 I've tried the following:
  
 session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('id','first_name')).all()
  
 which according to the documentation 
 (http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loading-with-multiple-entities)
  should work, but it throws an exception (ArgumentError: mapper option 
 expects string key or list of attributes)
  
 Can you please provide an example?
  
 check your SQLAlchemy version, I cannot reproduce that issue:
  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 jobs = relationship(Job)
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 first_name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
 'first_name')).all()
  
 output:
  
 SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS 
 job_1_first_name 
 FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id = job_1.employee_id
  
  
 
 
  
 Please notice that I'm trying to load only some properties of Employee 
 (including one relationship) while this behavior should not be the default 
 behavior (meaning that I don't want the defer the columns at model level)
 
 
 On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:
 On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com wrote: 
  Hi, 
  I have a model similar to the following: 
  
  class Employee(Base): 
  __tablename__ = t_employee 
  
  id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  first_name = sa.Column(sa.String(30)) 
  last_name = sa.Column(sa.String(30)) 
  phone_number = sa.Column(sa.String(30)) 
  
  _jobs = sa.orm.relationship(EmployeeJob, lazy=joined, cascade=all, 
  delete, delete-orphan) 
  
  @property 
  def name(self): 
  return self.first_name + (  + self.last_name if 
  len(self.last_name 
  or )  0 else ) 
  
  @property 
  def jobs(self): 
  return [item.job_id for item in sorted(self._jobs, 
  key=attrgetter('id'))] 
  
  @jobs.setter 
  def jobs(self, value): 
  self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
  
  class EmployeeJob(Base): 
  id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  employee_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_employee.id', 
  ondelete=CASCADE), nullable=False) 
  job_id = sa.Column(sa.BigInteger, sa.ForeignKey('t_job.id', 
  ondelete=CASCADE), nullable=False) 
  
  
  Now, I'm trying to write a simple query that will fetch all employees with 
  their jobs. 
  As I understand, I need to use joinedload so that the list of jobs will be 
  eagerly loaded but I can't understand 

Re: [sqlalchemy] Wrapping polymorphic model for Pyramid traversal

2014-09-04 Thread Milo Toor
OK, thanks for the reply Mike!

On Thursday, September 4, 2014 8:45:24 AM UTC-7, Michael Bayer wrote:

 this is probably more of a Pyramid question.

 I’m pretty allergic to traversal myself :)


 On Sep 3, 2014, at 2:58 PM, Milo Toor milo...@gmail.com javascript: 
 wrote:

 Hi.

 I am trying to wrap a polymorphic model so that it can act as a traversal 
 node in a Pyramid application:

 from sqlalchemy import Column, Integer, String, create_engine
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy.ext.declarative import declarative_base


 Base = declarative_base()
 engine = create_engine('sqlite:///:memory:', echo=True)
 Session = sessionmaker(bind=engine)


 # This is the class we wish to wrap
 class Employee(Base):
 __tablename__ = 'employee'
 id = Column(Integer, primary_key=True)
 name = Column(String(50))
 type = Column(String(20))


 __mapper_args__ = {
 'polymorphic_on': type,
 'polymorphic_identity': 'employee'
 }



 class Manager(Employee):
 __mapper_args__ = {
 'polymorphic_identity': 'manager'
 }



 class Engineer(Employee):
 __mapper_args__ = {
 'polymorphic_identity': 'engineer'
 }



 class EmployeeInTraversal(Employee):
 
 Wraps the Employee class. This is to keep our models and our 
 application
 logic decoupled.
 
 def __getitem__(self, key):
 
 Make the employee behave like a traversal node.

 :param key:
 The traversal key. If asked for tasks return the appropriate 
 root
 factory
 
 if key == 'tasks':
 return 'TasksRootFactory()'
 raise KeyError


 # Create the tables
 Base.metadata.create_all(engine)


 # Create both a Manager and an Engineer
 manager = Manager(name='Taylor')
 engineer = Engineer(name='Sam')


 session = Session()
 session.add_all([manager, engineer])
 session.commit()


 # somewhere a request is made for /employee/1/tasks...


 # Query for the engineer, somewhere in the EmployeeRootFactory
 wrapped_engineer = session.query(EmployeeInTraversal).get(1)


 # Traversal doing its thing. Here lies the trouble.
 engineer_tasks = wrapped_engineer['tasks']

 The last line of this code throws a TypeError with the message *'NoneType' 
 object has no attribute '__getitem__'*. Nothing is turned up by the query 
 to EmployeeInTraversal. If the query is instead made with the Employee 
 class, we get a similar TypeError: *'Manager' object has no attribute 
 '__getitem__'*. So in other words, querying EmployeeInTraversal returns 
 nothing, but querying Employee returns the object, although unwrapped.

 The reason for this, near as I can tell, is that the EmployeeInTraversal 
 class is being interpreted as a subtype of Employee rather than as a 
 wrapper for the class. I attribute this to the polymorphic nature of the 
 Employee class, but at this point I'm really just banging my head against 
 the wall. We would very much like to keep our models and application logic 
 separate, and not embed traversal logic in the schema classes... Is there 
 any way to wrap a polymorphic class without the wrapper being interpreted 
 as a sub-type?

 -- 
 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+...@googlegroups.com javascript:.
 To post to this group, send email to sqlal...@googlegroups.com 
 javascript:.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/d/optout.




-- 
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.


RE: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Nevertheless, is there a way to achieve what I want? (which is to
selectively load several columns and this 'jobs' property from Employee)

 

Thanks,

Ofir

 

 

From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On
Behalf Of Michael Bayer
Sent: Thursday, September 04, 2014 8:42 PM
To: sqlalchemy@googlegroups.com
Subject: Re: [sqlalchemy] selecting from a relationship

 

 

On Sep 4, 2014, at 1:32 PM, Ofir Herzas herz...@gmail.com wrote:





Thanks Michael,

I'm using 0.9.7 and while your example did work, the following did not:

 

Ok that's not a relationship().  joinedload() only works with relationships.

 

 

 





 

from sqlalchemy import *

from sqlalchemy.orm import *

from sqlalchemy.ext.declarative import declarative_base

 

Base = declarative_base()

 

class Employee(Base):

__tablename__ = 'employee'

 

id = Column(Integer, primary_key=True)

first_name = Column(String)

_jobs = relationship(EmployeeJob, lazy=joined)

 

@property

def jobs(self):

return [item.job_id for item in sorted(self._jobs,
key=attrgetter('id'))]

 

class EmployeeJob(Base):

__tablename__ = employee_job

 

id = Column(Integer, primary_key=True)

employee_id = Column(Integer, ForeignKey('employee.id'))

job_id = Column(Integer, ForeignKey('job.id'))

 

class Job(Base):

__tablename__ = 'job'

 

id = Column(Integer, primary_key=True)

name = Column(String)

 

e = create_engine(sqlite://, echo=True)

Base.metadata.create_all(e)

 

session = Session(e)

 

session.query(Employee).options(joinedload(Employee.jobs).load_only('id',
'first_name')).all()

 

 

Notice that the difference here is that I'm using a property decorator on
jobs, there is a link table (EmployeeJob), and I'm trying to load
information of Employee (first_name should be from there)

 

Thanks,

Ofir

 

From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On
Behalf Of Michael Bayer
Sent: Thursday, September 04, 2014 8:00 PM
To: sqlalchemy@googlegroups.com
Subject: Re: [sqlalchemy] selecting from a relationship

 

 

On Sep 4, 2014, at 12:28 PM, Ofir Herzas  mailto:herz...@gmail.com
herz...@gmail.com wrote:






Thanks Simon,

I've tried the following:

 

session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('
id','first_name')).all()

 

which according to the documentation (
http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loadi
ng-with-multiple-entities
http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loadin
g-with-multiple-entities) should work, but it throws an exception
(ArgumentError: mapper option expects string key or list of attributes)

 

Can you please provide an example?

 

check your SQLAlchemy version, I cannot reproduce that issue:

 

from sqlalchemy import *

from sqlalchemy.orm import *

from sqlalchemy.ext.declarative import declarative_base

 

Base = declarative_base()

 

class Employee(Base):

__tablename__ = 'employee'

 

id = Column(Integer, primary_key=True)

jobs = relationship(Job)

 

class Job(Base):

__tablename__ = 'job'

 

id = Column(Integer, primary_key=True)

employee_id = Column(Integer, ForeignKey('employee.id'))

first_name = Column(String)

 

e = create_engine(sqlite://, echo=True)

Base.metadata.create_all(e)

 

session = Session(e)

 

session.query(Employee).options(joinedload(Employee.jobs).load_only('id',
'first_name')).all()

 

output:

 

SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS
job_1_first_name 

FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id =
job_1.employee_id

 

 






 

Please notice that I'm trying to load only some properties of Employee
(including one relationship) while this behavior should not be the default
behavior (meaning that I don't want the defer the columns at model level)



On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:

On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com wrote: 
 Hi, 
 I have a model similar to the following: 
 
 class Employee(Base): 
 __tablename__ = t_employee 
 
 id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
 primary_key=True, nullable=False) 
 first_name = sa.Column(sa.String(30)) 
 last_name = sa.Column(sa.String(30)) 
 phone_number = sa.Column(sa.String(30)) 
 
 _jobs = sa.orm.relationship(EmployeeJob, lazy=joined,
cascade=all, 
 delete, delete-orphan) 
 
 @property 
 def name(self): 
 return self.first_name + (  + self.last_name if
len(self.last_name 
 or )  0 else ) 
 
 @property 
 def jobs(self): 
 return [item.job_id for item in sorted(self._jobs, 
 key=attrgetter('id'))] 
 
 @jobs.setter 
 def jobs(self, value): 
 self._jobs = [EmployeeJob(job_id=id_) for id_ in to_list(value)] 
 
 class EmployeeJob(Base): 
 id = sa.Column(sa.BigInteger, sa.Sequence('%s_id_seq' %

Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Simon King
You need to join along the actual relationships between your classes. You've 
got this:

Employee._jobs - EmployeeJob.? - Job

(I assume EmployeeJob has a job relationship to Job.)

I think you probably want something like this:

(session.query(Employee)
 .options(load_only('id', 'first_name'),
  joinedload(_jobs).joinedload(job))
).all()

Note that load_only is a separate option. The way you had it:

joinedload(Employee._jobs).load_only('id', 'first_name')

...would be looking for 'id' and 'first_name' columns on the EmployeeJob object.

There are lots of examples at:

  http://docs.sqlalchemy.org/en/latest/orm/loading.html

Hope that helps,

Simon

On 4 Sep 2014, at 19:17, Ofir Herzas herz...@gmail.com wrote:

 Nevertheless, is there a way to achieve what I want? (which is to selectively 
 load several columns and this 'jobs' property from Employee)
  
 Thanks,
 Ofir
  
  
 From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On 
 Behalf Of Michael Bayer
 Sent: Thursday, September 04, 2014 8:42 PM
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] selecting from a relationship
  
  
 On Sep 4, 2014, at 1:32 PM, Ofir Herzas herz...@gmail.com wrote:
 
 
 Thanks Michael,
 I'm using 0.9.7 and while your example did work, the following did not:
  
 Ok that's not a relationship().  joinedload() only works with relationships.
  
  
  
 
 
  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 first_name = Column(String)
 _jobs = relationship(EmployeeJob, lazy=joined)
  
 @property
 def jobs(self):
 return [item.job_id for item in sorted(self._jobs, 
 key=attrgetter('id'))]
  
 class EmployeeJob(Base):
 __tablename__ = employee_job
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 job_id = Column(Integer, ForeignKey('job.id'))
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
 'first_name')).all()
  
  
 Notice that the difference here is that I'm using a property decorator on 
 jobs, there is a link table (EmployeeJob), and I'm trying to load information 
 of Employee (first_name should be from there)
  
 Thanks,
 Ofir
  
 From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On 
 Behalf Of Michael Bayer
 Sent: Thursday, September 04, 2014 8:00 PM
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] selecting from a relationship
  
  
 On Sep 4, 2014, at 12:28 PM, Ofir Herzas herz...@gmail.com wrote:
 
 
 
 Thanks Simon,
 I've tried the following:
  
 session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_only('id','first_name')).all()
  
 which according to the documentation 
 (http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred-loading-with-multiple-entities)
  should work, but it throws an exception (ArgumentError: mapper option 
 expects string key or list of attributes)
  
 Can you please provide an example?
  
 check your SQLAlchemy version, I cannot reproduce that issue:
  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 jobs = relationship(Job)
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 first_name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('id', 
 'first_name')).all()
  
 output:
  
 SELECT employee.id AS employee_id, job_1.id AS job_1_id, job_1.first_name AS 
 job_1_first_name 
 FROM employee LEFT OUTER JOIN job AS job_1 ON employee.id = job_1.employee_id
  
  
 
 
 
  
 Please notice that I'm trying to load only some properties of Employee 
 (including one relationship) while this behavior should not be the default 
 behavior (meaning that I don't want the defer the columns at model level)
 
 
 On Thursday, September 4, 2014 5:59:21 PM UTC+3, Simon King wrote:
 On Thu, Sep 4, 2014 at 3:28 PM, Ofir Herzas her...@gmail.com wrote: 
  Hi, 
  I have a model similar to the following: 
  
  class Employee(Base): 
  __tablename__ = t_employee 
  
  id = sa.Column(Identifier, sa.Sequence('%s_id_seq' % __tablename__), 
  primary_key=True, nullable=False) 
  first_name = sa.Column(sa.String(30)) 
   

RE: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Thanks Simon, it worked!
I did the whole thing just because I had an sql select query talking 1.5
seconds to complete (several joins and many properties, just 1000 records),
and this change reduced it to 1.1 seconds (I guess I'll have to find a
better way to improve performance)


-Original Message-
From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On
Behalf Of Simon King
Sent: Thursday, September 04, 2014 11:14 PM
To: sqlalchemy@googlegroups.com
Subject: Re: [sqlalchemy] selecting from a relationship

You need to join along the actual relationships between your classes. You've
got this:

Employee._jobs - EmployeeJob.? - Job

(I assume EmployeeJob has a job relationship to Job.)

I think you probably want something like this:

(session.query(Employee)
 .options(load_only('id', 'first_name'),
  joinedload(_jobs).joinedload(job))
).all()

Note that load_only is a separate option. The way you had it:

joinedload(Employee._jobs).load_only('id', 'first_name')

...would be looking for 'id' and 'first_name' columns on the EmployeeJob
object.

There are lots of examples at:

  http://docs.sqlalchemy.org/en/latest/orm/loading.html

Hope that helps,

Simon

On 4 Sep 2014, at 19:17, Ofir Herzas herz...@gmail.com wrote:

 Nevertheless, is there a way to achieve what I want? (which is to 
 selectively load several columns and this 'jobs' property from 
 Employee)
  
 Thanks,
 Ofir
  
  
 From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] 
 On Behalf Of Michael Bayer
 Sent: Thursday, September 04, 2014 8:42 PM
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] selecting from a relationship
  
  
 On Sep 4, 2014, at 1:32 PM, Ofir Herzas herz...@gmail.com wrote:
 
 
 Thanks Michael,
 I'm using 0.9.7 and while your example did work, the following did not:
  
 Ok that's not a relationship().  joinedload() only works with
relationships.
  
  
  
 
 
  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 first_name = Column(String)
 _jobs = relationship(EmployeeJob, lazy=joined)
  
 @property
 def jobs(self):
 return [item.job_id for item in sorted(self._jobs, 
 key=attrgetter('id'))]
  
 class EmployeeJob(Base):
 __tablename__ = employee_job
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 job_id = Column(Integer, ForeignKey('job.id'))
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('i
 d', 'first_name')).all()
  
  
 Notice that the difference here is that I'm using a property decorator 
 on jobs, there is a link table (EmployeeJob), and I'm trying to load 
 information of Employee (first_name should be from there)
  
 Thanks,
 Ofir
  
 From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] 
 On Behalf Of Michael Bayer
 Sent: Thursday, September 04, 2014 8:00 PM
 To: sqlalchemy@googlegroups.com
 Subject: Re: [sqlalchemy] selecting from a relationship
  
  
 On Sep 4, 2014, at 12:28 PM, Ofir Herzas herz...@gmail.com wrote:
 
 
 
 Thanks Simon,
 I've tried the following:
  
 session.query(Employee).options(sa.orm.joinedload(Employee.jobs).load_
 only('id','first_name')).all()
  
 which according to the documentation 
 (http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#deferred
 -loading-with-multiple-entities) should work, but it throws an 
 exception (ArgumentError: mapper option expects string key or list of 
 attributes)
  
 Can you please provide an example?
  
 check your SQLAlchemy version, I cannot reproduce that issue:
  
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
  
 Base = declarative_base()
  
 class Employee(Base):
 __tablename__ = 'employee'
  
 id = Column(Integer, primary_key=True)
 jobs = relationship(Job)
  
 class Job(Base):
 __tablename__ = 'job'
  
 id = Column(Integer, primary_key=True)
 employee_id = Column(Integer, ForeignKey('employee.id'))
 first_name = Column(String)
  
 e = create_engine(sqlite://, echo=True)
 Base.metadata.create_all(e)
  
 session = Session(e)
  
 session.query(Employee).options(joinedload(Employee.jobs).load_only('i
 d', 'first_name')).all()
  
 output:
  
 SELECT employee.id AS employee_id, job_1.id AS job_1_id, 
 job_1.first_name AS job_1_first_name FROM employee LEFT OUTER JOIN job 
 AS job_1 ON employee.id = job_1.employee_id
  
  
 
 
 
  
 Please notice that I'm trying to load only some properties of Employee 
 (including one 

Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Jonathan Vanasco


On Thursday, September 4, 2014 2:19:34 PM UTC-4, Ofir Herzas wrote:

 Nevertheless, is there a way to achieve what I want? (which is to 
 selectively load several columns and this 'jobs' property from Employee)


The ways I usually do that are:

1.  Select the other object.  Query for EmployeeJob, and then load only 
the Employee columns.  

2. Explicitly load columns.  I'm not sure if this will work for 
relationships:

  session.query( TableClass.column_a, TableClass.column_b).all()

instead of returning an ORM object, you get a tuple.

3. Define a column as deferred in the mapper 
[ 
http://docs.sqlalchemy.org/en/latest/orm/mapper_config.html#deferred-column-loading]

Looking at your example though, unless you have very high traffic -- you're 
not going to have a significant performance gain with a query like that. 
 Your tables don't have many columns, and they're not very large.  People 
are usually concerned about load_only when you have very large fields 
(BLOBS, TEXT, HSTORE) or complex joins and need to save memory.

You might just be better off letting the ORM load stuff you don't need -- 
you'll get much more code done that way.

-- 
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.


Re: [sqlalchemy] selecting from a relationship

2014-09-04 Thread Ofir Herzas
Thanks Jonathan,
I actually have more properties and relationships which were removed for
the sake of the example.
You are right though, the performance gain was not as I hoped it would be.

I'll have to think of other methods (caching maybe)...
On Sep 4, 2014 11:50 PM, Jonathan Vanasco jonat...@findmeon.com wrote:



 On Thursday, September 4, 2014 2:19:34 PM UTC-4, Ofir Herzas wrote:

 Nevertheless, is there a way to achieve what I want? (which is to
 selectively load several columns and this 'jobs' property from Employee)


 The ways I usually do that are:

 1.  Select the other object.  Query for EmployeeJob, and then load only
 the Employee columns.

 2. Explicitly load columns.  I'm not sure if this will work for
 relationships:

   session.query( TableClass.column_a, TableClass.column_b).all()

 instead of returning an ORM object, you get a tuple.

 3. Define a column as deferred in the mapper [
 http://docs.sqlalchemy.org/en/latest/orm/mapper_config.html#deferred-column-loading
 ]

 Looking at your example though, unless you have very high traffic --
 you're not going to have a significant performance gain with a query like
 that.  Your tables don't have many columns, and they're not very large.
  People are usually concerned about load_only when you have very large
 fields (BLOBS, TEXT, HSTORE) or complex joins and need to save memory.

 You might just be better off letting the ORM load stuff you don't need --
 you'll get much more code done that way.

 --
 You received this message because you are subscribed to a topic in the
 Google Groups sqlalchemy group.
 To unsubscribe from this topic, visit
 https://groups.google.com/d/topic/sqlalchemy/OprfrGJcoJU/unsubscribe.
 To unsubscribe from this group and all its topics, 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.


-- 
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.


[sqlalchemy] Session.close() appears to infrequently not expunge all objects

2014-09-04 Thread Lonnie Hutchinson
 

I am using sqlalchemy 0.8.5 with mysql 5.5 and think an intermittent 
failure I am seeing may be due to an issue in sqlalchemy. Very infrequently 
I receive an error from Session.add() stating the instance is already 
attached to session 'XXX' (this is 'YYY') (see below for stack trace). I 
understand the typical reason this error is raised, but I do not believe 
the instance should still be attached to XXX, even though it was shortly 
before (milliseconds) since Session.close() was called on the session. A 
second session is created, and in the vast majority of cases the objects 
from the first session can be added to the second session without error, 
but occasionally (1% of the time) add() raises InvalidRequestError. 

My understanding of Session.close() is that upon return all instances 
should be detached from the session and their instance state session_id 
attribute should no longer reference the session. This does not appear to 
be happening since adding the instance to a different session fails since 
the instance is still attached to the previous session. 

In reading the code it appears as though it is expected in certain 
situations for the session_id to continue to refer to the session after 
close since the check for already attached checks session_id as well as 
whether the session remains in the sessions registry. 

I have created a patch to check not only the instance state reference to 
the session but also check whether the session still contains the instance 
before raising the InvalidRequestError, but I do not have a way to 
reproduce this issue outside our production system, and am very leery of 
hacking sqlalchemy for a production system with my limited understanding of 
session internals. 

I would appreciate any comments on possible causes of the symptoms I am 
seeing as well as comments on the wisdom of applying this patch and running 
it in a production system. 

I am in the process of upgrading to sqlalchemy 0.9.7 but that is at least a 
month away and hope to make traction on this issue before then. I also do 
not believe upgrading will help since there are no sqlalchemy bugs on this. 


TIA for any advice or suggestions you have. 



diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py 

index dcb68d6..b06e624 100644 

--- a/lib/sqlalchemy/orm/session.py 

+++ b/lib/sqlalchemy/orm/session.py 

@@ -1749,10 +1749,13 @@ class Session(_SessionClassMethods): 

if state.session_id and \ 

state.session_id is not self.hash_key and \ 

state.session_id in _sessions: 

- raise sa_exc.InvalidRequestError( 

- Object '%s' is already attached to session '%s'  

- (this is '%s') % (orm_util.state_str(state), 

- state.session_id, self.hash_key)) 

+ other_session = _sessions.get(state.session_id, None) 

+ if other_session and (other_session.identity_map.contains_state(state) or 

+ state in other_session._new): 

+ raise sa_exc.InvalidRequestError( 

+ Object '%s' is already attached to session '%s'  

+ (this is '%s') % (orm_util.state_str(state), 

+ state.session_id, self.hash_key)) 




if state.session_id != self.hash_key: 

if include_before and 




Stack trace: 

File snip, line 81, in quota_allocation_management 

yield 

File snip, line 235, in __init__ 

tx.add(self.configuration) 

File snip, line 35, in __call 

return attr(*args, **kwargs) 

File 
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py,
 
line 1399, in add 

self._save_or_update_state(state) 

File 
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py,
 
line 1418, in _save_or_update_state 

self._save_or_update_impl(st_) 

File 
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py,
 
line 1667, in _save_or_update_impl 

self._update_impl(state) 

File 
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py,
 
line 1661, in _update_impl 

self._attach(state) 

File 
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py,
 
line 1755, in _attach 

state.session_id, self.hash_key))

-- 
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.


[sqlalchemy] Issue with return results

2014-09-04 Thread Horcle
I had to reinstall my python dev environment from scratch due to a hd 
failure, and in the process something seems to have changed. 

When querying against MS SQL using the script (test_conenction.py):
import pyodbc
import sqlalchemy
from sqlalchemy.engine import reflection
from sqlalchemy.engine.reflection import Inspector

def connect():
return pyodbc.connect(
'DRIVER={FreeTDS};SERVER=server.ip.address;'
'DATABASE=STUDY_PARTICIPANT;UID=test;PWD=test;port=1433;CHARSET=utf8;'
'TDS_Version=9.1;')
engine = sqlalchemy.create_engine('mssql+pyodbc://', creator=connect, 
encoding='latin1',echo='debug',supports_unicode_binds=False)
conn = engine.connect()
print conn

for row in engine.execute('select 6 * 7 as [Result];'):
print row.Result

insp = reflection.Inspector.from_engine(engine)
table_name = 'irb_desc'
table_names = insp.get_table_names()
if table_name not in table_names:
print 'A: ' + table_name

I used to get the following nice output:

python test_connect.py
2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine
   SELECT default_schema_name FROM
   sys.database_principals
   WHERE principal_id=database_principal_id()

2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine ()
2014-08-18 16:15:06,613 DEBUG sqlalchemy.engine.base.Engine Col (
'default_schema_name',)
2014-08-18 16:15:06,614 DEBUG sqlalchemy.engine.base.Engine Row (u'dbo', )
2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
plain returns' AS VARCHAR(60)) AS anon_1
2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine ()
2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
unicode returns' AS NVARCHAR(60)) AS anon_1
2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine ()
sqlalchemy.engine.base.Connection object at 0x101877ed0
2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine select 6 * 7 as [
Result];
2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine ()
2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Col ('Result',)
2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Row (42, )
42
2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine SELECT [TABLES_1
].[TABLE_NAME]
FROM [INFORMATION_SCHEMA].[TABLES] AS [TABLES_1]
WHERE [TABLES_1].[TABLE_SCHEMA] = CAST(? AS NVARCHAR(max)) AND [TABLES_1].[
TABLE_TYPE] = ? ORDER BY [TABLES_1].[TABLE_NAME]
2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine ('dbo', 'BASE 
TABLE')
2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Col (
'TABLE_NAME',)
2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irb_desc'
, )
2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irbd', )
2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u
'study_desc', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'study_irb', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'study_status', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'study_status_desc', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'study_subject', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'subj_desc', )
2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
'subj_status_desc', )
2014-08-18 16:15:06,665 DEBUG sqlalchemy.engine.base.Engine Row (u
'subject_status', )
2014-08-18 16:15:06,665 DEBUG sqlalchemy.engine.base.Engine Row (u
'sysdiagrams', )


Now, in my updated environment, it looks like this:

python test_connect.py
2014-09-04 15:26:05,974 INFO sqlalchemy.engine.base.Engine
SELECT default_schema_name FROM
sys.database_principals
WHERE principal_id=database_principal_id()

2014-09-04 15:26:05,974 INFO sqlalchemy.engine.base.Engine ()
2014-09-04 15:26:05,976 DEBUG sqlalchemy.engine.base.Engine Col 
('default_schema_name',)
2014-09-04 15:26:05,976 DEBUG sqlalchemy.engine.base.Engine Row 
(u'd\x00b\x00o\x00', )
2014-09-04 15:26:05,978 INFO sqlalchemy.engine.base.Engine SELECT 
CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2014-09-04 15:26:05,978 INFO sqlalchemy.engine.base.Engine ()
2014-09-04 15:26:05,981 INFO sqlalchemy.engine.base.Engine SELECT 
CAST('test unicode returns' AS NVARCHAR(60)) AS anon_1
2014-09-04 15:26:05,981 INFO sqlalchemy.engine.base.Engine ()
sqlalchemy.engine.base.Connection object at 0x10fda1510
2014-09-04 15:26:06,000 INFO sqlalchemy.engine.base.Engine select 6 * 7 as 
[Result];
2014-09-04 15:26:06,001 INFO sqlalchemy.engine.base.Engine ()
2014-09-04 15:26:06,002 DEBUG sqlalchemy.engine.base.Engine Col ('Result',)
2014-09-04 15:26:06,002 DEBUG sqlalchemy.engine.base.Engine Row (42, )
42
2014-09-04 15:26:06,007 INFO sqlalchemy.engine.base.Engine SELECT 
[TABLES_1].[TABLE_NAME]
FROM [INFORMATION_SCHEMA].[TABLES] AS [TABLES_1]
WHERE [TABLES_1].[TABLE_SCHEMA] = CAST(? AS NVARCHAR(max)) AND 
[TABLES_1].[TABLE_TYPE] = ? ORDER BY [TABLES_1].[TABLE_NAME]
2014-09-04 

[sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Ken Lareau
So I have a few tables as follows (abbreviated for unnecessary columns):

class Project(Base):
__tablename__ = 'projects'

id = Column(u'project_id', INTEGER(), primary_key=True)

applications = relationship(
'AppDefinition',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
lazy=False,
)

package_definitions = relationship(
'PackageDefinition',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
)


class PackageDefinition(Base):
__tablename__ = 'package_definitions'

id = Column(u'pkg_def_id', INTEGER(), primary_key=True)

applications = relationship(
'AppDefinition',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
)

projects = relationship(
'Project',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
)


class AppDefinition(Base):
__tablename__ = 'app_definitions'

id = Column(u'AppID', SMALLINT(display_width=2), primary_key=True)

package_definitions = relationship(
'PackageDefinition',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
)

projects = relationship(
'Project',
secondary=lambda: Base.metadata.tables['project_package'],
passive_deletes=True,
)


class ProjectPackage(Base):
__tablename__ = 'project_package'

project_id = Column(
INTEGER(),
ForeignKey('projects.project_id', ondelete='cascade'),
primary_key=True
)
pkg_def_id = Column(
INTEGER(),
ForeignKey('package_definitions.pkg_def_id', ondelete='cascade'),
primary_key=True
)
app_id = Column(
SMALLINT(display_width=6),
ForeignKey('app_definitions.AppID', ondelete='cascade'),
primary_key=True
)

app_definition = relationship('AppDefinition', uselist=False)
package_definition = relationship('PackageDefinition', uselist=False)
project = relationship('Project', uselist=False)


If I select a row from the projects table and try to delete it, when I try
to commit
the session I get something like this:

[INFO] DELETE FROM project_package WHERE project_package.project_id = ? AND
project_package.app_id = ?
[INFO] (1L, 1L)
[INFO] DELETE FROM project_package WHERE project_package.project_id = ? AND
project_package.pkg_def_id = ?
[INFO] (1L, 1L)
[INFO] ROLLBACK

At the time of the delete, the project_package table simply has this:

[('project_id', 1L), ('pkg_def_id', 1L), ('app_id', 1L)]

Obviously the combination of the ondelete='cascade' settings in the
project_package table and the 'passive_deletes' settings in the
relationships
is what's triggering this, but after try many different searches on Google,
I'm
not finding the right solution to fix this; obviously I only want it to
attempt to
delete the row once, but each relationship in project is triggering its own
delete which is bad.

So... help?  Am I missing something simple here, or is my model not good
enough to do the right thing?

-- 
- Ken Lareau

-- 
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.


Re: [sqlalchemy] Session.close() appears to infrequently not expunge all objects

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 5:00 PM, Lonnie Hutchinson lonn...@skytap.com wrote:

 
 
 I am using sqlalchemy 0.8.5 with mysql 5.5 and think an intermittent failure 
 I am seeing may be due to an issue in sqlalchemy. Very infrequently I receive 
 an error from Session.add() stating the instance is already attached to 
 session 'XXX' (this is 'YYY') (see below for stack trace). I understand the 
 typical reason this error is raised, but I do not believe the instance should 
 still be attached to XXX, even though it was shortly before (milliseconds) 
 since Session.close() was called on the session.

OK I'm seeing some red flags here.  I see the word intermittent, which almost 
always means, multiple threads.  Then I see the word, milliseconds.   Are 
we using threads?  Are we trying to time things?   Because looking at 0.8.5, 
when you call close(), the objects in that Session are absolutely de-assocaited 
with that Session, including that session_id is set to None.

This is very simple to confirm:

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

Base = declarative_base()

class A(Base):
__tablename__ = 'a'

id = Column(Integer, primary_key=True)

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

sess = Session(e)
a1 = A()
sess.add(a1)
sess.commit()

assert a1._sa_instance_state.session_id == sess.hash_key
sess.close()
assert a1._sa_instance_state.session_id is None

there's no milliseconds here.  close() completes, and that id is gone.

If you are playing with threads, the only way to guarantee one thread finishes 
something before the other starts is to either join() that thread or use 
mutexes.


 My understanding of Session.close() is that upon return all instances should 
 be detached from the session and their instance state session_id attribute 
 should no longer reference the session. This does not appear to be happening 
 since adding the instance to a different session fails since the instance is 
 still attached to the previous session. 

Above I illustrate that this is not the case.   The code path is clear:

session.py - line 942 - close() calls:
session.py - line 952 - self.expunge_all()
session.py - line 965 calls state._detach() on everything in identity + _new.  
 (question.  are you trying to move an object that was deleted?   that might 
have issues, but that's not a valid use case).
state.py - line 166 - _detach() calls:
state.py - line 167:   self.session_id = self._strong_obj = None

 In reading the code it appears as though it is expected in certain situations 
 for the session_id to continue to refer to the session after close since the 
 check for already attached checks session_id as well as whether the session 
 remains in the sessions registry. 

I'm not seeing that in 0.8.5 at all.what line of code are you referring to ?


-- 
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.


Re: [sqlalchemy] Issue with return results

2014-09-04 Thread Michael Bayer
SQL Server and unix, many things can change:

- UnixODBC version
- FreeTDS version  (0.82 and 0.91 have *extremely* different behaviors)
- FreeTDS configuration

The first place I'd look in this case would be your freetds.conf, you probably 
need to configure the character set correctly in there.



On Sep 4, 2014, at 5:06 PM, Horcle g...@umn.edu wrote:

 I had to reinstall my python dev environment from scratch due to a hd 
 failure, and in the process something seems to have changed. 
 
 When querying against MS SQL using the script (test_conenction.py):
 import pyodbc
 import sqlalchemy
 from sqlalchemy.engine import reflection
 from sqlalchemy.engine.reflection import Inspector
 
 def connect():
 return pyodbc.connect(
   'DRIVER={FreeTDS};SERVER=server.ip.address;'
   
 'DATABASE=STUDY_PARTICIPANT;UID=test;PWD=test;port=1433;CHARSET=utf8;'
   'TDS_Version=9.1;')
 engine = sqlalchemy.create_engine('mssql+pyodbc://', creator=connect, 
 encoding='latin1',echo='debug',supports_unicode_binds=False)
 conn = engine.connect()
 print conn
 
 for row in engine.execute('select 6 * 7 as [Result];'):
 print row.Result
 
 insp = reflection.Inspector.from_engine(engine)
 table_name = 'irb_desc'
 table_names = insp.get_table_names()
 if table_name not in table_names:
 print 'A: ' + table_name
 
 I used to get the following nice output:
 
 python test_connect.py
 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine
SELECT default_schema_name FROM
sys.database_principals
WHERE principal_id=database_principal_id()
 
 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,613 DEBUG sqlalchemy.engine.base.Engine Col 
 ('default_schema_name',)
 2014-08-18 16:15:06,614 DEBUG sqlalchemy.engine.base.Engine Row (u'dbo', )
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 plain returns' AS VARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 unicode returns' AS NVARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine ()
 sqlalchemy.engine.base.Connection object at 0x101877ed0
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine select 6 * 7 as 
 [Result];
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Col ('Result',)
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Row (42, )
 42
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine SELECT 
 [TABLES_1].[TABLE_NAME]
 FROM [INFORMATION_SCHEMA].[TABLES] AS [TABLES_1]WHERE 
 [TABLES_1].[TABLE_SCHEMA] = CAST(? AS NVARCHAR(max)) AND 
 [TABLES_1].[TABLE_TYPE] = ? ORDER BY [TABLES_1].[TABLE_NAME]
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine ('dbo', 'BASE 
 TABLE')
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Col 
 ('TABLE_NAME',)
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irb_desc', 
 )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irbd', )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'study_desc', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'study_irb', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'study_status', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'study_status_desc', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'study_subject', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'subj_desc', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'subj_status_desc', )
 2014-08-18 16:15:06,665 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'subject_status', )
 2014-08-18 16:15:06,665 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'sysdiagrams', )
 
 
 Now, in my updated environment, it looks like this:
 
 python test_connect.py
 2014-09-04 15:26:05,974 INFO sqlalchemy.engine.base.Engine
 SELECT default_schema_name FROM
 sys.database_principals
 WHERE principal_id=database_principal_id()
 
 2014-09-04 15:26:05,974 INFO sqlalchemy.engine.base.Engine ()
 2014-09-04 15:26:05,976 DEBUG sqlalchemy.engine.base.Engine Col 
 ('default_schema_name',)
 2014-09-04 15:26:05,976 DEBUG sqlalchemy.engine.base.Engine Row 
 (u'd\x00b\x00o\x00', )
 2014-09-04 15:26:05,978 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 plain returns' AS VARCHAR(60)) AS anon_1
 2014-09-04 15:26:05,978 INFO sqlalchemy.engine.base.Engine ()
 2014-09-04 15:26:05,981 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 unicode returns' AS NVARCHAR(60)) AS anon_1
 2014-09-04 15:26:05,981 INFO sqlalchemy.engine.base.Engine ()
 sqlalchemy.engine.base.Connection object at 0x10fda1510
 2014-09-04 15:26:06,000 INFO sqlalchemy.engine.base.Engine select 6 * 7 as 
 

Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 5:37 PM, Ken Lareau klar...@tagged.com wrote:

 So I have a few tables as follows (abbreviated for unnecessary columns):
 
 class Project(Base):
 __tablename__ = 'projects'
 
 id = Column(u'project_id', INTEGER(), primary_key=True)
 
 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 lazy=False,
 )
 
 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class PackageDefinition(Base):
 __tablename__ = 'package_definitions'
 
 id = Column(u'pkg_def_id', INTEGER(), primary_key=True)
 
 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class AppDefinition(Base):
 __tablename__ = 'app_definitions'
 
 id = Column(u'AppID', SMALLINT(display_width=2), primary_key=True)
 
 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class ProjectPackage(Base):
 __tablename__ = 'project_package'
 
 project_id = Column(
 INTEGER(),
 ForeignKey('projects.project_id', ondelete='cascade'),
 primary_key=True
 )
 pkg_def_id = Column(
 INTEGER(),
 ForeignKey('package_definitions.pkg_def_id', ondelete='cascade'),
 primary_key=True
 )
 app_id = Column(
 SMALLINT(display_width=6),
 ForeignKey('app_definitions.AppID', ondelete='cascade'),
 primary_key=True
 )
 
 app_definition = relationship('AppDefinition', uselist=False)
 package_definition = relationship('PackageDefinition', uselist=False)
 project = relationship('Project', uselist=False)

this model has serious issues, though it can be made to hobble along with some 
small changes.  The three way association table is not a great pattern in the 
first place.  Additionally, using that same table as secondary in all those 
places is clearly the issue here, and they don't even have back_populates 
between them, which are used in many-to-many in order to try avoid double 
deleting.   But that wouldn't solve the issue here anyway.

In this case, you have mapped to the project_package table directly; you're 
using the association object pattern.  The note at the end of 
http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#association-object 
applies here - you absolutely should have viewonly=True on all of those 
relationship() directives that refer to this association table as the 
secondary table.  The ORM otherwise has no way to know what changes should 
result in what deletions where.


-- 
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.


Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Ken Lareau
On Thu, Sep 4, 2014 at 3:30 PM, Michael Bayer mike...@zzzcomputing.com
wrote:


 On Sep 4, 2014, at 5:37 PM, Ken Lareau klar...@tagged.com wrote:

 So I have a few tables as follows (abbreviated for unnecessary columns):

 class Project(Base):
 __tablename__ = 'projects'

 id = Column(u'project_id', INTEGER(), primary_key=True)

 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 lazy=False,
 )

 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class PackageDefinition(Base):
 __tablename__ = 'package_definitions'

 id = Column(u'pkg_def_id', INTEGER(), primary_key=True)

 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )

 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class AppDefinition(Base):
 __tablename__ = 'app_definitions'

 id = Column(u'AppID', SMALLINT(display_width=2), primary_key=True)

 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )

 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class ProjectPackage(Base):
 __tablename__ = 'project_package'

 project_id = Column(
 INTEGER(),
 ForeignKey('projects.project_id', ondelete='cascade'),
 primary_key=True
 )
 pkg_def_id = Column(
 INTEGER(),
 ForeignKey('package_definitions.pkg_def_id', ondelete='cascade'),
 primary_key=True
 )
 app_id = Column(
 SMALLINT(display_width=6),
 ForeignKey('app_definitions.AppID', ondelete='cascade'),
 primary_key=True
 )

 app_definition = relationship('AppDefinition', uselist=False)
 package_definition = relationship('PackageDefinition', uselist=False)
 project = relationship('Project', uselist=False)


 this model has serious issues, though it can be made to hobble along with
 some small changes.  The “three way association table” is not a great
 pattern in the first place.  Additionally, using that same table as
 “secondary” in all those places is clearly the issue here, and they don’t
 even have back_populates between them, which are used in many-to-many in
 order to try avoid “double deleting”.   But that wouldn’t solve the issue
 here anyway.


As I feared, I figured this model would be frowned upon. :)  Note that this
model (or the underlying database)
is not set in stone; if you have suggestions on a better way to link the
three main tables, I would love to hear
it (and we did add back_populates (somehow missed them during the
restructuring of the models), but as
you said, didn't help in this case).



 In this case, you have mapped to the project_package table directly;
 you’re using the association object pattern.  The note at the end of
 http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#association-object
 applies here - you absolutely should have viewonly=True on all of those
 relationship() directives that refer to this association table as the
 “secondary” table.  The ORM otherwise has no way to know what changes
 should result in what deletions where.


Will add the 'viewonly' option as suggested and see if that helps, but as
mentioned above, if you can suggest
a better model for this case, please let me know!

-- 
- Ken Lareau

-- 
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.


Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 6:58 PM, Ken Lareau klar...@tagged.com wrote:

 On Thu, Sep 4, 2014 at 3:30 PM, Michael Bayer mike...@zzzcomputing.com 
 wrote:
 
 On Sep 4, 2014, at 5:37 PM, Ken Lareau klar...@tagged.com wrote:
 
 So I have a few tables as follows (abbreviated for unnecessary columns):
 
 class Project(Base):
 __tablename__ = 'projects'
 
 id = Column(u'project_id', INTEGER(), primary_key=True)
 
 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 lazy=False,
 )
 
 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class PackageDefinition(Base):
 __tablename__ = 'package_definitions'
 
 id = Column(u'pkg_def_id', INTEGER(), primary_key=True)
 
 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class AppDefinition(Base):
 __tablename__ = 'app_definitions'
 
 id = Column(u'AppID', SMALLINT(display_width=2), primary_key=True)
 
 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )
 
 
 class ProjectPackage(Base):
 __tablename__ = 'project_package'
 
 project_id = Column(
 INTEGER(),
 ForeignKey('projects.project_id', ondelete='cascade'),
 primary_key=True
 )
 pkg_def_id = Column(
 INTEGER(),
 ForeignKey('package_definitions.pkg_def_id', ondelete='cascade'),
 primary_key=True
 )
 app_id = Column(
 SMALLINT(display_width=6),
 ForeignKey('app_definitions.AppID', ondelete='cascade'),
 primary_key=True
 )
 
 app_definition = relationship('AppDefinition', uselist=False)
 package_definition = relationship('PackageDefinition', uselist=False)
 project = relationship('Project', uselist=False)
 
 this model has serious issues, though it can be made to hobble along with 
 some small changes.  The three way association table is not a great pattern 
 in the first place.  Additionally, using that same table as secondary in 
 all those places is clearly the issue here, and they don't even have 
 back_populates between them, which are used in many-to-many in order to try 
 avoid double deleting.   But that wouldn't solve the issue here anyway.
 
 As I feared, I figured this model would be frowned upon. :)  Note that this 
 model (or the underlying database)
 is not set in stone; if you have suggestions on a better way to link the 
 three main tables, I would love to hear
 it (and we did add back_populates (somehow missed them during the 
 restructuring of the models), but as
 you said, didn't help in this case).

A row in the 3-way table means that for this project_id, and pkg_def_id, and 
app_id, that's a single allowed value, so that's star schema, OK (though they 
call star schema denormalized - i don't exactly understand why, if you make 
all the columns part of the primary key).  But then you have functions that 
give you lists of things based on two-column slices of that table, in order to 
relate different dimensions to each other; projects-app_definitions, means you 
can have Project (X) - AppDefnition(Y) any number of times, for every value of 
pkg_def_id.I guess that's the awkward part here.   Those aren't really 
collection-based relationships so much as analytical queries across dimension 
tables.   They are valid queries but aren't really object/relational - when 
we map a class to another with a many-to-many collection in between, that means 
something more specific.

So maybe its just, object relational mapping assumes certain patterns are 
mappable to objects and collections, and 3-way associations aren't quite in 
that pattern :).





-- 
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.


Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Ken Lareau
On Thu, Sep 4, 2014 at 4:35 PM, Michael Bayer mike...@zzzcomputing.com
wrote:


 On Sep 4, 2014, at 6:58 PM, Ken Lareau klar...@tagged.com wrote:

 On Thu, Sep 4, 2014 at 3:30 PM, Michael Bayer mike...@zzzcomputing.com
 wrote:


 On Sep 4, 2014, at 5:37 PM, Ken Lareau klar...@tagged.com wrote:

 So I have a few tables as follows (abbreviated for unnecessary columns):

 class Project(Base):
 __tablename__ = 'projects'

 id = Column(u'project_id', INTEGER(), primary_key=True)

 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 lazy=False,
 )

 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class PackageDefinition(Base):
 __tablename__ = 'package_definitions'

 id = Column(u'pkg_def_id', INTEGER(), primary_key=True)

 applications = relationship(
 'AppDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )

 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class AppDefinition(Base):
 __tablename__ = 'app_definitions'

 id = Column(u'AppID', SMALLINT(display_width=2), primary_key=True)

 package_definitions = relationship(
 'PackageDefinition',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )

 projects = relationship(
 'Project',
 secondary=lambda: Base.metadata.tables['project_package'],
 passive_deletes=True,
 )


 class ProjectPackage(Base):
 __tablename__ = 'project_package'

 project_id = Column(
 INTEGER(),
 ForeignKey('projects.project_id', ondelete='cascade'),
 primary_key=True
 )
 pkg_def_id = Column(
 INTEGER(),
 ForeignKey('package_definitions.pkg_def_id', ondelete='cascade'),
 primary_key=True
 )
 app_id = Column(
 SMALLINT(display_width=6),
 ForeignKey('app_definitions.AppID', ondelete='cascade'),
 primary_key=True
 )

 app_definition = relationship('AppDefinition', uselist=False)
 package_definition = relationship('PackageDefinition', uselist=False)
 project = relationship('Project', uselist=False)


 this model has serious issues, though it can be made to hobble along with
 some small changes.  The “three way association table” is not a great
 pattern in the first place.  Additionally, using that same table as
 “secondary” in all those places is clearly the issue here, and they don’t
 even have back_populates between them, which are used in many-to-many in
 order to try avoid “double deleting”.   But that wouldn’t solve the issue
 here anyway.


 As I feared, I figured this model would be frowned upon. :)  Note that
 this model (or the underlying database)
 is not set in stone; if you have suggestions on a better way to link the
 three main tables, I would love to hear
 it (and we did add back_populates (somehow missed them during the
 restructuring of the models), but as
 you said, didn't help in this case).


 A row in the 3-way table means that for this project_id, and pkg_def_id,
 and app_id, that’s a single allowed value, so that’s star schema, OK
 (though they call star schema “denormalized” - i don’t exactly understand
 why, if you make all the columns part of the primary key).  But then you
 have functions that give you lists of things based on two-column slices of
 that table, in order to relate different dimensions to each other;
 projects-app_definitions, means you can have Project (X) -
 AppDefnition(Y) any number of times, for every value of pkg_def_id.I
 guess that’s the awkward part here.   Those aren’t really collection-based
 “relationships” so much as analytical queries across dimension tables.
 They are valid queries but aren’t really “object/relational” - when we map
 a class to another with a many-to-many collection in between, that means
 something more specific.

 So maybe its just, object relational mapping assumes certain patterns are
 mappable to objects and collections, and 3-way associations aren’t quite in
 that pattern :).


Hmm, understood, though the main reason for these relationships were to
avoid having to make
DB queries within the main application code (pushing them out into the
models) and simplify the
logic; if you had seen what our application code looked like before, you
might shudder even more
than over what we're doing here. :)

Is there a way to essentially allow something like 'for app in
project.applications:' without having
to make an explicit query to the DB first, but avoiding the awkwardness of
the current setup?

-- 
- Ken Lareau

-- 
You received this message because you are 

Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 7:50 PM, Ken Lareau klar...@tagged.com wrote:

 
 Is there a way to essentially allow something like 'for app in 
 project.applications:' without having
 to make an explicit query to the DB first, but avoiding the awkwardness of 
 the current setup? 

just use the viewonly=True and we can all go home :)  I'm not too upset about it


-- 
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.


Re: [sqlalchemy] Session.close() appears to infrequently not expunge all objects

2014-09-04 Thread Lonnie Hutchinson
The session executes in one of many web-server threads, but there is no
multi-threading with respect to the session or the objects. The session
that was closed is within an initializer and upon return a method on the
object is executed that creates a new session and tries to attach objects
retrieved from the first session. This method does spawn threads but the
exception happens before any threads are spawned. The thread target does
not take objects, only python strings. only identifiers used in new
sessions to query the objects again. The milliseconds I referred to are
between the close() of the first session and the add() that fails in the
second session.

The code I say appears to expect the session_id to remain on detached
states in certain situations is that the check in Session._attach checks
not only the session_id but that the referenced session still exists in
_sessions:
if state.session_id and \
state.session_id is not self.hash_key and \
state.session_id in _sessions:
raise sa_exc.InvalidRequestError(
Object '%s' is already attached to session '%s' 
(this is '%s') % (orm_util.state_str(state),
state.session_id, self.hash_key))

I am interested in this in the hopes that sheds light on the source of the
intermittent failures.

In debugging this I have noticed that after the first session has been
closed() and the initializer has returned the session remains in _sessions.
However, if I call gc.collect() the session is removed, suggesting it just
hasn't been fully cleaned up yet. Since it takes both the state referencing
the session and the session still existing in _sessions, I can't help but
wonder if this is a gc issue. Unfortunately it is not feasible to add
gc.collect() calls in our production application as it introduces too much
overhead.


On Thu, Sep 4, 2014 at 3:20 PM, Michael Bayer mike...@zzzcomputing.com
wrote:


 On Sep 4, 2014, at 5:00 PM, Lonnie Hutchinson lonn...@skytap.com wrote:

 
 
  I am using sqlalchemy 0.8.5 with mysql 5.5 and think an intermittent
 failure I am seeing may be due to an issue in sqlalchemy. Very infrequently
 I receive an error from Session.add() stating the instance is already
 attached to session 'XXX' (this is 'YYY') (see below for stack trace). I
 understand the typical reason this error is raised, but I do not believe
 the instance should still be attached to XXX, even though it was shortly
 before (milliseconds) since Session.close() was called on the session.

 OK I'm seeing some red flags here.  I see the word intermittent, which
 almost always means, multiple threads.  Then I see the word,
 milliseconds.   Are we using threads?  Are we trying to time things?
  Because looking at 0.8.5, when you call close(), the objects in that
 Session are absolutely de-assocaited with that Session, including that
 session_id is set to None.

 This is very simple to confirm:

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

 Base = declarative_base()

 class A(Base):
 __tablename__ = 'a'

 id = Column(Integer, primary_key=True)

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

 sess = Session(e)
 a1 = A()
 sess.add(a1)
 sess.commit()

 assert a1._sa_instance_state.session_id == sess.hash_key
 sess.close()
 assert a1._sa_instance_state.session_id is None

 there's no milliseconds here.  close() completes, and that id is gone.

 If you are playing with threads, the only way to guarantee one thread
 finishes something before the other starts is to either join() that thread
 or use mutexes.


  My understanding of Session.close() is that upon return all instances
 should be detached from the session and their instance state session_id
 attribute should no longer reference the session. This does not appear to
 be happening since adding the instance to a different session fails since
 the instance is still attached to the previous session.

 Above I illustrate that this is not the case.   The code path is clear:

 session.py - line 942 - close() calls:
 session.py - line 952 - self.expunge_all()
 session.py - line 965 calls state._detach() on everything in identity +
 _new.   (question.  are you trying to move an object that was deleted?
  that might have issues, but that's not a valid use case).
 state.py - line 166 - _detach() calls:
 state.py - line 167:   self.session_id = self._strong_obj = None

  In reading the code it appears as though it is expected in certain
 situations for the session_id to continue to refer to the session after
 close since the check for already attached checks session_id as well as
 whether the session remains in the sessions registry.

 I'm not seeing that in 0.8.5 at all.what line of code are you
 referring to ?


 --
 You received this message because you are subscribed to the Google Groups
 sqlalchemy group.
 To 

Re: [sqlalchemy] Multiple delete attempts of same rows with a star schema configuration

2014-09-04 Thread Ken Lareau
On Thu, Sep 4, 2014 at 4:54 PM, Michael Bayer mike...@zzzcomputing.com
wrote:


 On Sep 4, 2014, at 7:50 PM, Ken Lareau klar...@tagged.com wrote:


 Is there a way to essentially allow something like 'for app in
 project.applications:' without having
 to make an explicit query to the DB first, but avoiding the awkwardness of
 the current setup?


 just use the viewonly=True and we can all go home :)  I’m not too upset
 about it


Got it... the change worked fine, thanks for all the help. :)

-- 
- Ken Lareau

-- 
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.


Re: [sqlalchemy] Session.close() appears to infrequently not expunge all objects

2014-09-04 Thread Michael Bayer

On Sep 4, 2014, at 8:17 PM, Lonnie Hutchinson lonn...@skytap.com wrote:

 The session executes in one of many web-server threads, but there is no 
 multi-threading with respect to the session or the objects. The session that 
 was closed is within an initializer and upon return a method on the object is 
 executed that creates a new session and tries to attach objects retrieved 
 from the first session. This method does spawn threads but the exception 
 happens before any threads are spawned. The thread target does not take 
 objects, only python strings. only identifiers used in new sessions to query 
 the objects again. The milliseconds I referred to are between the close() of 
 the first session and the add() that fails in the second session.
 
 The code I say appears to expect the session_id to remain on detached states 
 in certain situations is that the check in Session._attach checks not only 
 the session_id but that the referenced session still exists in _sessions:
 if state.session_id and \
 state.session_id is not self.hash_key and \
 state.session_id in _sessions:
 raise sa_exc.InvalidRequestError(
 Object '%s' is already attached to session '%s' 
 (this is '%s') % (orm_util.state_str(state),
 state.session_id, self.hash_key))
 
 I am interested in this in the hopes that sheds light on the source of the 
 intermittent failures.

yeah that code is intended to detect when an object is added to a session that 
hasn't been removed from another.

However, the implementation for session.close() has a direct trace that leads 
to the session_id set to None for all objects that are either in the identity 
map, or in the _new (pending) collection.  There's no ambiguity there.

 In debugging this I have noticed that after the first session has been 
 closed() and the initializer has returned the session remains in _sessions. 
 However, if I call gc.collect() the session is removed, suggesting it just 
 hasn't been fully cleaned up yet.

that's not really accurate.  There's a collection of all the Sessions in the 
weak referencing map _sessions, and Python's GC may not in fact remove those 
sessions in a deterministic way.  But that has no bearing upon testing objects 
that have been removed from that session, and therefore have no session_id, if 
they belong to that session - their session_id has been cleared out.


 Since it takes both the state referencing the session and the session still 
 existing in _sessions, I can't help but wonder if this is a gc issue. 
 Unfortunately it is not feasible to add gc.collect() calls in our production 
 application as it introduces too much overhead.

I will tell you how this *can* happen.  If you have a Session, and you put 
objects in it, then you *don't* close the session; the session just is 
dereferenced, and is garbage collected at some point by the above mentioned 
weak dictionary.   The objects within that session will *not* have anything 
done to their session_id in that case.   If a new session is started up, and it 
happens to take over the same in-memory ID as the one that was just GC'ed, it 
will have the same hash key, and will then exist within _sessions.  Then you 
move your objects to a third session; they will in fact have a session_id that 
is represented in _sessions, albeit against a different session than they 
started with, and you get the error.

So if that's the case, then the issue here is the result of objects belonging 
to ad-hoc sessions that are not closed() explicitly, then those objects are 
shuttled along to another session, while busy thread mechanics in the 
background keep creating new sessions that occasionally use the same session 
identifier and produce this collision.

There's ways to test for this, like assigning a unique counter to each Session 
within an event, like the begin() event, then using the before_attach event to 
verify that session_id is None, and if not, take a peek at that Session and its 
counter, compare it to something on the state.




-- 
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.


Re: [sqlalchemy] Issue with return results

2014-09-04 Thread Horcle
Thanks. I forgot to mention that I had tried adding the encoding scheme to 
freetds.conf. I also tried other encoding schemes, all to no avail. I may 
try pymssql tomorrow to see what that does. I would have tried mxodbc, but 
I am not about to pay $379 for a driver. I may also see if I can get the MS 
ODBC driver for Linux to work on my Mac. 

I have to say that the MS SQL stuff is a royal PITA, but unfortunately, 
that is what I am stuck with at work. Uggh. (;_;)

The version of FreeTDS I have been using has always been 9.1 (although, I 
noticed that the Brew formula for it changed in the last few days to 9.1_1, 
for what that's worth).

Greg--

On Thursday, September 4, 2014 5:23:02 PM UTC-5, Michael Bayer wrote:

 SQL Server and unix, many things can change:

 - UnixODBC version
 - FreeTDS version  (0.82 and 0.91 have *extremely* different behaviors)
 - FreeTDS configuration

 The first place I’d look in this case would be your freetds.conf, you 
 probably need to configure the character set correctly in there.



 On Sep 4, 2014, at 5:06 PM, Horcle g...@umn.edu javascript: wrote:

 I had to reinstall my python dev environment from scratch due to a hd 
 failure, and in the process something seems to have changed. 

 When querying against MS SQL using the script (test_conenction.py):
 import pyodbc
 import sqlalchemy
 from sqlalchemy.engine import reflection
 from sqlalchemy.engine.reflection import Inspector

 def connect():
 return pyodbc.connect(
 'DRIVER={FreeTDS};SERVER=server.ip.address;'
 'DATABASE=STUDY_PARTICIPANT;UID=test;PWD=test;port=1433;CHARSET=utf8;'
 'TDS_Version=9.1;')
 engine = sqlalchemy.create_engine('mssql+pyodbc://', creator=connect, 
 encoding='latin1',echo='debug',supports_unicode_binds=False)
 conn = engine.connect()
 print conn

 for row in engine.execute('select 6 * 7 as [Result];'):
 print row.Result

 insp = reflection.Inspector.from_engine(engine)
 table_name = 'irb_desc'
 table_names = insp.get_table_names()
 if table_name not in table_names:
 print 'A: ' + table_name

 I used to get the following nice output:

 python test_connect.py
 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine
SELECT default_schema_name FROM
sys.database_principals
WHERE principal_id=database_principal_id()

 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,613 DEBUG sqlalchemy.engine.base.Engine Col (
 'default_schema_name',)
 2014-08-18 16:15:06,614 DEBUG sqlalchemy.engine.base.Engine Row (u'dbo', )
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 plain returns' AS VARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine SELECT CAST('test 
 unicode returns' AS NVARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine ()
 sqlalchemy.engine.base.Connection object at 0x101877ed0
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine select 6 * 7 as 
 [Result];
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Col ('Result'
 ,)
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Row (42, )
 42
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine SELECT [
 TABLES_1].[TABLE_NAME]
 FROM [INFORMATION_SCHEMA].[TABLES] AS [TABLES_1]WHERE [TABLES_1].[
 TABLE_SCHEMA] = CAST(? AS NVARCHAR(max)) AND [TABLES_1].[TABLE_TYPE] = ? 
 ORDER BY [TABLES_1].[TABLE_NAME]
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine ('dbo', 'BASE 
 TABLE')
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Col (
 'TABLE_NAME',)
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u
 'irb_desc', )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irbd', 
 )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u
 'study_desc', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
 'study_irb', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row span 
 style=color: #660; class=st

 ...

-- 
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.


[sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-04 Thread Alex Grönholm
The following code fails with AttributeError: 'NoneType' object has no 
attribute 'concrete':

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import AbstractConcreteBase, 
declarative_base

Base = declarative_base()


class Document(Base, AbstractConcreteBase):
type = Column(Unicode, nullable=False)


class ContactDocument(Document):
__abstract__ = True

send_method = Column('sendmethod', Unicode)


class ActualDocument(ContactDocument):
__tablename__ = 'actual_documents'
__mapper_args__ = {'concrete': True, 'polymorphic_identity': 'actual'}

id = Column(Integer, primary_key=True)

configure_mappers()


Am I not supposed to have more than one level of abstract base classes? Or 
am I doing something else wrong?
This is with SQLAlchemy 0.9.7.

-- 
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.


Re: [sqlalchemy] More than one level of abstract base classes doesn't work

2014-09-04 Thread Michael Bayer
well that's just a simple bug.  this fixes:

diff --git a/lib/sqlalchemy/ext/declarative/api.py 
b/lib/sqlalchemy/ext/declarative/api.py
index daf8bff..fe64ee7 100644
--- a/lib/sqlalchemy/ext/declarative/api.py
+++ b/lib/sqlalchemy/ext/declarative/api.py
@@ -396,7 +396,7 @@ class AbstractConcreteBase(ConcreteBase):
 
 for scls in cls.__subclasses__():
 sm = _mapper_or_none(scls)
-if sm.concrete and cls in scls.__bases__:
+if sm and sm.concrete and cls in scls.__bases__:
 sm._set_concrete_base(m)
 

if you want to post a bug report, or send a PR + test, whatever, that would 
help...


for whatever reason this mapping is generating a crapload of warnings too.
Oh, I think its because ConcreteBase hardcodes that name type in the 
polymorphic join, if you change that col name to type_foo they go away.

the concrete base classes aren't very smooth (nor is concrete mapping 
overall...)




On Sep 4, 2014, at 9:37 PM, Alex Grönholm alex.gronh...@nextday.fi wrote:

 The following code fails with AttributeError: 'NoneType' object has no 
 attribute 'concrete':
 
 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import AbstractConcreteBase, declarative_base
 
 Base = declarative_base()
 
 
 class Document(Base, AbstractConcreteBase):
 type = Column(Unicode, nullable=False)
 
 
 class ContactDocument(Document):
 __abstract__ = True
 
 send_method = Column('sendmethod', Unicode)
 
 
 class ActualDocument(ContactDocument):
 __tablename__ = 'actual_documents'
 __mapper_args__ = {'concrete': True, 'polymorphic_identity': 'actual'}
 
 id = Column(Integer, primary_key=True)
 
 configure_mappers()
 
 
 Am I not supposed to have more than one level of abstract base classes? Or am 
 I doing something else wrong?
 This is with SQLAlchemy 0.9.7.
 
 -- 
 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.

-- 
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.


Re: [sqlalchemy] Issue with return results

2014-09-04 Thread Greg Silverman
I think I am going to dump SQL Server and just go with Postgres. Much
easier, and less of a headache. Fortunately, we are not yet in production.

Thanks!

Greg--


On Thu, Sep 4, 2014 at 8:31 PM, Horcle g...@umn.edu wrote:

 Thanks. I forgot to mention that I had tried adding the encoding scheme to
 freetds.conf. I also tried other encoding schemes, all to no avail. I may
 try pymssql tomorrow to see what that does. I would have tried mxodbc, but
 I am not about to pay $379 for a driver. I may also see if I can get the MS
 ODBC driver for Linux to work on my Mac.

 I have to say that the MS SQL stuff is a royal PITA, but unfortunately,
 that is what I am stuck with at work. Uggh. (;_;)

 The version of FreeTDS I have been using has always been 9.1 (although, I
 noticed that the Brew formula for it changed in the last few days to 9.1_1,
 for what that's worth).

 Greg--

 On Thursday, September 4, 2014 5:23:02 PM UTC-5, Michael Bayer wrote:

 SQL Server and unix, many things can change:

 - UnixODBC version
 - FreeTDS version  (0.82 and 0.91 have *extremely* different behaviors)
 - FreeTDS configuration

 The first place I’d look in this case would be your freetds.conf, you
 probably need to configure the character set correctly in there.



 On Sep 4, 2014, at 5:06 PM, Horcle g...@umn.edu wrote:

 I had to reinstall my python dev environment from scratch due to a hd
 failure, and in the process something seems to have changed.

 When querying against MS SQL using the script (test_conenction.py):
 import pyodbc
 import sqlalchemy
 from sqlalchemy.engine import reflection
 from sqlalchemy.engine.reflection import Inspector

 def connect():
 return pyodbc.connect(
 'DRIVER={FreeTDS};SERVER=server.ip.address;'
 'DATABASE=STUDY_PARTICIPANT;UID=test;PWD=test;port=1433;CHARSET=utf8;'
 'TDS_Version=9.1;')
 engine = sqlalchemy.create_engine('mssql+pyodbc://', creator=connect,
 encoding='latin1',echo='debug',supports_unicode_binds=False)
 conn = engine.connect()
 print conn

 for row in engine.execute('select 6 * 7 as [Result];'):
 print row.Result

 insp = reflection.Inspector.from_engine(engine)
 table_name = 'irb_desc'
 table_names = insp.get_table_names()
 if table_name not in table_names:
 print 'A: ' + table_name

 I used to get the following nice output:

 python test_connect.py
 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine
SELECT default_schema_name FROM
sys.database_principals
WHERE principal_id=database_principal_id()

 2014-08-18 16:15:06,611 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,613 DEBUG sqlalchemy.engine.base.Engine Col (
 'default_schema_name',)
 2014-08-18 16:15:06,614 DEBUG sqlalchemy.engine.base.Engine Row (u'dbo',
 )
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine SELECT CAST('test
 plain returns' AS VARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,616 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine SELECT CAST('test
 unicode returns' AS NVARCHAR(60)) AS anon_1
 2014-08-18 16:15:06,619 INFO sqlalchemy.engine.base.Engine ()
 sqlalchemy.engine.base.Connection object at 0x101877ed0
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine select 6 * 7
 as [Result];
 2014-08-18 16:15:06,639 INFO sqlalchemy.engine.base.Engine ()
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Col ('Result'
 ,)
 2014-08-18 16:15:06,641 DEBUG sqlalchemy.engine.base.Engine Row (42, )
 42
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine SELECT [
 TABLES_1].[TABLE_NAME]
 FROM [INFORMATION_SCHEMA].[TABLES] AS [TABLES_1]WHERE [TABLES_1].[
 TABLE_SCHEMA] = CAST(? AS NVARCHAR(max)) AND [TABLES_1].[TABLE_TYPE] = ?
 ORDER BY [TABLES_1].[TABLE_NAME]
 2014-08-18 16:15:06,647 INFO sqlalchemy.engine.base.Engine ('dbo', 'BASE
 TABLE')
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Col (
 'TABLE_NAME',)
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u
 'irb_desc', )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u'irbd',
 )
 2014-08-18 16:15:06,663 DEBUG sqlalchemy.engine.base.Engine Row (u
 'study_desc', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row (u
 'study_irb', )
 2014-08-18 16:15:06,664 DEBUG sqlalchemy.engine.base.Engine Row span
 style=color: #660; class=st

 ...

  --
 You received this message because you are subscribed to a topic in the
 Google Groups sqlalchemy group.
 To unsubscribe from this topic, visit
 https://groups.google.com/d/topic/sqlalchemy/-i4-GQpXkzY/unsubscribe.
 To unsubscribe from this group and all its topics, 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.




-- 
Greg M. Silverman
Senior Developer Analyst
Cardiovascular Informatics http://www.med.umn.edu/cardiology/