Re: [sqlalchemy] update using query - joint table inheritance

2013-08-10 Thread Michael Bayer

On Aug 9, 2013, at 10:45 PM, Mark Eastwood markeastwoo...@gmail.com wrote:

 It is easier to describe in code than in words.

absolutely, this is much preferred.


 Can anyone please tell me if there is something that I am doing wrong? is 
 this a bug with sqlalchemy?

it's kind of a bug, yes, the biggest bug here is that the docs for 
query.update() are very underdetailed in this respect, as there is a huge 
caveat regarding multi-table mappings here.

your query will work on MySQL, Postgresql, and SQL Server if you do it like 
this:

updated = query.filter(Parent.id==Child.id).update({'value': 4})


this because an UPDATE is traditionally against a single table only, however in 
SQLA 0.8 the ability to support so-called multiple table updates was added, a 
feature supported in very different ways by these three backends.  So updating 
against Child, which is really a combination of the parent, child tables 
particularly since your WHERE criteria is against the parent, puts both tables 
into the UPDATE statement, but the mechanism currently does not add the 
joining criteria for the Parent to Child.Such an UPDATE wasn't even 
possible prior to 0.8 and also won't work on backends like SQLite or Oracle at 
all since they don't support multi-table updates.

These kinds of issues can be diagnosed by setting echo=True on your Engine, 
then looking to see what's actually going wrong with the query.

but we need a ticket for this in trac b.c. the docs don't even provide a hint 
of this.




signature.asc
Description: Message signed with OpenPGP using GPGMail


Re: [sqlalchemy] update using query - joint table inheritance

2013-08-10 Thread Mark Eastwood
Hi Michael,

Thankyou very much for your reply, which is exactly what I needed. I also 
saw the new ticket that was raised for documentation of this, thankyou 
zzzeek.

Mark

-- 
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/groups/opt_out.




[sqlalchemy] update using query - joint table inheritance

2013-08-09 Thread Mark Eastwood
Hi all,

I am getting some unexpected behaviour when trying to update selected rows 
from a query when using joint table inheritance. Using MySQL, a query that 
is filtered based on items in the parent table, does not honour this filter 
when updating items in the child table (all children are updated, not only 
those matching the filter). It is easier to describe in code than in words. 
The code is attached.

In an attempt to make it easier to run, I did try and make the script use 
sqlite instead of MySQL, however in this case an entirely different error 
resulted. I have therefore included both (MySQL enabled, sqlite disabled by 
default).

Can anyone please tell me if there is something that I am doing wrong? is 
this a bug with sqlalchemy?

Thankyou,

Mark Eastwood

-- 
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/groups/opt_out.
'''
Demonstrate a (bug?) in updating records via a query


I am getting some unexpected behaviour when trying to update selected rows from
a query when using joint table inheritance. Using MySQL, a query that is
filtered based on items in the parent table, does not honour this filter when
updating items in the child table (all children are updated, not only those
matching the filter).

In an attempt to make it easier to run, I did try and make the script use
sqlite instead of MySQL, however in this case an entirely different error
resulted. I have therefore included both (MySQL enabled, sqlite disabled by
default).

With MySQL
--

All records within the Child table get updated. What should happen is just the
one record that matches the query gets updated

With SQLite
---

The query raises an OperationalError

Other Debug Info


I have tried this on two different systems with the same result. There are:

System 1:

Operating system: Windows 7 64 bit
Python version = 3.3.1
SQLAlchemy version = 0.8.0
MySQL version = 5.6.13
- included mysqlconnector from windows installer (v1.0.11)

System 2:

Operating system: Windows 7 32 bit
Python v3.3.1
SQLAlchemy v0.8.2
Mariadb version = 5.5.32
MySQLConnector version = 1.0.11
 
To run this script, MySQL (or Mariadb) needs to be installed and a user by the
name of 'tester' with password 'test_password' needs to have access to the
database 'test'@'localhost'. Of course, you can change these.

'''

from sqlalchemy import *
from sqlalchemy.exc import DatabaseError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

###
# Uncomment one of the following engines
###

#engine = create_engine('sqlite://')

engine = create_engine('mysql+mysqlconnector://%s:%s@%s:%s/%s' % \
  ('tester', 'test_password', '127.0.0.1', '3306', 'test'))

#--

Base = declarative_base()
Base.metadata.bind = engine
session = sessionmaker(bind=engine)()

class Parent(Base):
__tablename__ = 'parent'

id = Column(INTEGER(), primary_key=True)
name = Column(VARCHAR(255), unique=True)
type = Column(VARCHAR(255))

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

class Child(Parent):
__tablename__ = 'child'
__mapper_args__ = {'polymorphic_identity': 'Child'}

id = Column(INTEGER(), ForeignKey(Parent.id), primary_key=True)
value = Column(INTEGER(255))

def __repr__(self):
return '%s %s' % (self.name, self.value)

###
# Start with a clean database
###

# MySQL warns if these tables don't exist, despite using IF EXISTS
# SQLAlchemy interprets these as errors, just ignore
try:
session.execute('DROP TABLE IF EXISTS child, parent;')
except DatabaseError:
pass

###
# Build a simple table
###

Base.metadata.create_all()
session.add_all([Child(name='Steven', value=1), 
 Child(name='Mark', value=2), 
 Child(name='Daniel', value=3)])
session.flush()
print('We have three records in the database')
print(session.query(Child).all())

query =