[sqlalchemy] Re: Any libraries or examples of how to let users define custom fields on SA tables/objects

2010-04-21 Thread Ants Aasma
On Apr 18, 10:43 pm, Randy Syring ra...@rcs-comp.com wrote:
 So, this seems like a relatively common paradigm and I was hoping
 someone might already know of a library or example application for
 using SA to accomplish this.  I am looking for something akin to
 Rail's acts_as_cutomizable plugin (http://github.com/trappist/
 acts_as_customizable) for SA.

The pattern is actually called an entity-attribute-value model.
There's
an example implementation with an EAV table in SQLAlchemy
examples. [1]

Depending on your particular circumstances you might want to use
an alternate implementation. Things that might affect your decision
are the distribution of values, datatype requirements, what kinds of
queries are required, what features the database engine supports.
I have a PostgreSQL hstore based implementation somewhere,
but I can't find it right now.

 [1] http://www.sqlalchemy.org/trac/browser/examples/vertical

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: joining sessions / two phase commit

2010-02-09 Thread Ants Aasma
On Feb 9, 10:48 am, Chris Withers ch...@simplistix.co.uk wrote:
 Okay, but what does the transaction manager do that's different from
 calling commit on session1 and session2 in order?

A TM should write to durable storage when a transaction group is
prepared before committing any transaction. When doing crash recovery
this information must be used to decide whether to commit or rollback
the rest of the prepared transactions.

  The second transaction will remain in a prepared
  state (modifications not visible to other transactions, still holding
  any locks), even after a database crash and restart.

 So how do you un-f?$k it then? ;-)

For MySQL you can obtain the list of prepared transactions with the XA
RECOVER command. You can then use XA COMMIT or XA ROLLBACK commands as
appropriate to handle them.

 I know that zope's transaction package aims to do just this, I wonder if
 anyone's used that, or anything else, with SA to solve this problem?

I've only used two phase for the relatively trivial case of doing
filesystem updates atomically along with metadata updates in the
database. The zope transaction package doesn't seem to have any
disaster recovery story, but maybe I'm missing something. Depending on
your exact environment and requirements you might also find an easier
way, but be very-very careful with distributed transactions. It's a
really hard problem to get 100% correct in the face of arbitrary
software, network and hardware failures.

Ants

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: joining sessions / two phase commit

2010-02-08 Thread Ants Aasma
On Feb 4, 12:41 am, Chris Withers ch...@simplistix.co.uk wrote:
 The problem is that session2 (and it's engine) are only created in a
 small part of the code, while session1 is created in a much wider
 encompassing framework. As such, there's no obvious way to get session1
 to the piece of code that calls commit on session2.

 (an aside: what happens here, assuming the first of your possibilities:
 session1.commit()
 raise RuntimeError('something goes bang')
 session2.commit())

This is the reason why you need a transaction manager when using two-
phase transactions. The second transaction will remain in a prepared
state (modifications not visible to other transactions, still holding
any locks), even after a database crash and restart. The transaction
manager needs to ensure that all transactions in a group either get
committed or are rolled back. This should preferably be an automatic
process, as any prepared transactions left hanging will grind your
database to a halt pretty quickly.

Ants

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



[sqlalchemy] Re: Simple example of checking for containment

2009-08-29 Thread Ants Aasma

With the SQL layer:
update(foo_tbl, not_(foo_tbl.c.explanation.in_(select
([turnover_tbl.c.reason],
whereclause=and_(turnover_tbl.c.datasource == 'blah',
turnover_tbl.c.turnover == 0)
))),
values={'turnover': 1})

With the ORM layer:
sess.query(Foo).filter(~Foo.explanation.in_(
sess.query(Turnover.reason).filter_by(datasource='blah',
turnover=0)
)).update({'turnover': 1})

On Aug 28, 11:47 pm, Victor Ng crankyco...@gmail.com wrote:
 I can't seem to figure out how to tell sqlalchemy to do something
 like :

 UPDATE Foo
 SET turnover = 1
 WHERE EXPLANATION NOT IN(SELECT Reason FROM mbsIsTurnoverXLAT where
 Datasource ='blah' and Isturnover=0)
 AND DATASOURCE = 'blah'

 The not in clause is the part that's tripping me up.  I'm not sure
 how to express that using the query api with raw Table objects.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: ORM query with overlaps operator

2009-08-21 Thread Ants Aasma

This is something that could be improved in SQLAlchemy, but as a
workaround you can use the compiler extension to create the support
yourself. Here's some example code. It uses some private internals
from SQLAlchemy so you need to keep an eye on it that it doesn't break
when changing versions.

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql import ClauseElement
from sqlalchemy.sql.expression import _literal_as_binds, _CompareMixin
from sqlalchemy.types import NullType

class TupleClause(ClauseElement, _CompareMixin):
def __init__(self, *columns):
self.columns = [_literal_as_binds(col) for col in columns]
self.type = NullType()

@compiles(TupleClause)
def compile_tupleclause(element, compiler, **kw):
return (%s) % , .join(compiler.process(col) for col in
element.columns)

# Usage:
def overlaps(a_pair, b_pair):
return TupleClause(*a_pair).op('OVERLAPS')(TupleClause(*b_pair))

query.filter(overlaps((MappedClass.start_col, MappedClass.end_col),
(start_time, end_time)))


On Aug 21, 10:50 am, David Bolen db3l@gmail.com wrote:
 Has anyone generated ORM queries using the OVERLAPS SQL operator that
 reference columns in the tables in the query?  I've been experimenting
 with various approaches and can't seem to cleanly get the column names
 (with their appropriate alias based on the rest of the query) into the
 overlaps clause.

 I'm basically issuing an ORM query and want to check that the date
 range given by two columns in one of the objects being queried is
 overlaps with a computed date range.  In some cases the object whose
 columns I am checking is the primary target of the query whereas in
 others it's a joined class.

 I found an older post from March where Michael suggested the form

     somexpression.op('OVERLAPS', someotherexpression)

 but I can't figure out how to apply that, and in particular what sort
 of expression will produce a tuple at the SQL layer, yet still support
 the op method?  Namely the output needs to be of the form:

     (start, stop) OVERLAPS (start, stop)

 So I figured I'd try straight text, and was attempting something like:

     query(MappedClass).
       filter('(:c_start, :c_end) overlaps (:start, :end)').
       params(c_start=MappedClass.start_col, c_end=MappedClass.end_col,
              start=datetimevalue, end=datetimevalue)

 but I'm having trouble identifying an appropriate value for the
 c_start/c_end params to generate the column names in the resulting
 SQL.  The above gives can't adapt the InstrumentedAttribute references
 in the params.

 In the meantime I can fall back to a pure textual filter which will
 have to assume how the mapped class will be aliased, but that feels
 fragile and it'd be nice if I could let SQLAlchemy generate the column
 names somehow.  I get the feeling though that OVERLAPS is a bit
 unusual in terms of the necessary support since it has non-scalar left
 and right values for the operator.

 Thanks for any help.

 -- David
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Bug in ORM: SA 0.5.5.

2009-08-18 Thread Ants Aasma

On Aug 18, 2:37 am, Jon Nelson jnel...@jamponi.net wrote:
 Since the database has a default the insert works (although I would
 suggest that SA might consider grumping under circumstances like
 this).

This is ticket #1457. (http://www.sqlalchemy.org/trac/ticket/1457)
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: too eager loading

2009-08-17 Thread Ants Aasma

On Aug 17, 12:41 pm, matiskiva mati.sk...@mobileye.com wrote:
 The problem being that i get a huge SQL statement with [effectively]
 two joins, where the sequences and rects are joint to the detections.
 It is very slow and creates extra data [as for every rect there is
 also an occurance of sequence and so on]
 The best thing to do is to perform an eager load of rects. Than in a
 seperate statement an eager load of sequences and attach them to the
 entities
 But i do not know how to instruct SQL Alchemy to do that. Generally it
 seems that the power of multiple queries and temporary tables is not
 used much.

Yeah, two to-many eagerloads effectively generate a cartesian product
that can get slow pretty fast with increasing number of entities.
SQLAlchemy doesn't have enough information to figure out the correct
strategy automtically and no-one has had the time to implement an API
to create multi step queries.
You can still do that manually:
detections = query.options(eagerload('sequences')).all()
session.query(DetectionDB).filter(DetectionDB.id.in_([d.id for d in
detections])).options(eagerload('rects'))
This will populate the eagerloaded collections in two queries.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: filtering eagerloaded properties?

2009-08-13 Thread Ants Aasma

There are two reasonable options for this, one is to select tuples of
group, user, task and join them together with appropriate conditions:

session.query(Group, User, Task).outerjoin(Group.users).outerjoin
((Task, (Task.user_id == User.id)  ~Task.complete))

the other option is to create a new relation on User that encapsulates
the derived relation to incomplete tasks:

mapper(User, users_tbl, properties=dict(
incomplete_tasks = relation(Task, viewonly=True, primaryjoin=
(users_tbl.c.id == tasks_tbl.c.user_id)  ~tasks_tbl.c.complete)
))
now you can eagerload that collection:

session.query(Group).options(eagerload_all('users.incomplete_tasks'))
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: how sum elements with filters

2009-08-13 Thread Ants Aasma

Something like the following should work:

session.query(Position, func.sum(Stats.points)).join(Stats.league,
Player.position)\
.filter(Player.team == 'Some team').group_by(Position)



On Aug 11, 9:08 pm, Doron Tal doron.tal.l...@gmail.com wrote:
 Hi sqlalchemy,

 I'm a newbie to SA. I hope you could help me with the following problem.

 Say that I have:

 class Position(Base):
     __tablename__ = 'Position'
     id = Column('id', Integer, primary_key=True)
     position = Column('name', String) #center, guard etc'

 class Player(Base):
     __tablename__ = 'Player'
     id = Column('id', Integer, primary_key=True)
     name = Column('name', String)
     team = Column('team', String)
     position_id = Column('position_id', Integer, ForeignKey('Position.id'))
     position = relation('Position')

 class Stats(Base):
     __tablename__ = 'Stats'
     id = Column('id', Integer, primary_key=True)
     name = Column('name', String)
     points = Column('points', Integer)
     Player_id = Column('player_id', Integer, ForeignKey('Player.id'))
     league = relation('Player')

 How can I retrieve the sum of points for each of the player positions? In
 other words:
 Retrieving the sum of points of all of the guards, centers, etc'.
 How can this query be further limited to a specific team (simple
 join+filter, right?)

 Thanks,
 Doron.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: share objects with threads and scoped_session

2009-08-06 Thread Ants Aasma

On Aug 5, 10:59 pm, drakkan drakkan1...@gmail.com wrote:
 Seems that once I defined a scoped session as:

 Session = scoped_session(sessionmaker())

 I can switch to a non scoped session simply calling:

 sess=Session()
...
 is this the intended behaviuor?

Yes that is intended behavior. But if you are using a session across
threads be aware that sessions are not thread-safe. You shouldn't do
anything that modifies the session concurrently, that includes
Session.add and Session.query, but also triggering lazyloads on
objects or modifying their attributes.

See http://www.sqlalchemy.org/docs/05/session.html#frequently-asked-questions
for some discussion.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: GIS support for SQLAlchemy

2009-08-06 Thread Ants Aasma

I don't have a lot of experience with geodatabases so I can't evaluate
this from a practical perspective, but I do have a couple of thoughts
about the general design.

I'm not too keen on having the geometry functions as methods on the
comparator. Having them there creates a namespace collision hazard. In
my opinion it would be cleaner and closer to the OGC spec to have
something akin to the generic function framework
(sqlalchemy.sql.functions) that integrates into the compilation
framework via sqlalchemy.ext.compiler. Looking at the db specific
modules, a lot of the repetition there could be factored out by a data
driven approach, having a base implementation and a per dialect
dictionary that maps OGC function names to db implementation names.

Also the GeometryDDL and Geometry classes could use some refactoring
to support extensibility of adding new dialects. Probably via a
registry that maps dialects to their geometry implementations. Also,
the GeometryDDL doesn't account for the fact that dialects could be
subclassed.

But generally seems a useful endeavor. Best of luck to you on
polishing it.

On Aug 5, 5:56 pm, Sanjiv Singh singhsanj...@gmail.com wrote:
 Hi,

 I have been working on supporting spatial data types and spatial
 operations on SQLAlchemy as my summer of code project. The code is
 available athttp://bitbucket.org/sanjiv/geoalchemy/ and a demo TG2
 app using it is athttp://geo.turbogears.org/.

 I started out by following the postgis example included in sqlalchemy
 package. Till now I have added support for PostGIS, MySQL and
 Spatialite.

 It would be nice to have some suggestions / criticisms before I make
 the first release. I am quite sure the code needs a lot of
 improvement.

 regards
 Sanjiv
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: GIS support for SQLAlchemy

2009-08-06 Thread Ants Aasma

On Aug 6, 4:09 pm, Sanjiv Singh singhsanj...@gmail.com wrote:
  Also the GeometryDDL and Geometry classes could use some refactoring
  to support extensibility of adding new dialects. Probably via a
  registry that maps dialects to their geometry implementations. Also,
  the GeometryDDL doesn't account for the fact that dialects could be
  subclassed.

 I am not sure I totally understand the solution you are suggesting.
 Could you elaborate a bit more? Is there some code I could look at
 that does something similar?

Regular refactoring of if's to a class hierarchy. Create a base
strategy class that defines the template methods for before-create,
after-create etc. and then put the DB specific implementations into db
specific subclasses that can live in the db specific modules.
(geoalchemy.postgis.PGGeometyDDL etc.) To create the objects use a
dict to map dialects to GeometryDDL implementations:

ddl_registry = {
('sqlalchemy.databases.postgres', 'PGDialect'): PGGeometryDDL,
...
}

def dialect_to_ddl_impl(dialect):
for cls in type(dialect).__mro__:
cls_id = cls.__module__, cls.__name__
if cls_id in ddl_registry:
return ddl_registry[cls_id]()
else:
raise NotImplementedError

This allows other implementers to add their class to the ddl_registry
and support other databases without changing your code. You could even
use setuptools entry points to handle the registering part. Something
like this is in sqlalchemy.engine.url.URL.get_dialect.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: How to filter by the result of a subquery?

2009-07-16 Thread Ants Aasma

On Jul 16, 2:55 am, The Devil's Programmer
thedevilsprogram...@gmail.com wrote:
 I believe I am supposed to wrap the whole query inside another query
 and put the where clause on the outer query, would this be correct? I
 have tried messing around with this a little but haven't managed to
 get it to work yet. If somebody could just tell me that I'm on the
 right track, that would be great.

First check that the database doesn't figure it out for you. A quick
test on my sample database showed that on postgres this doesn't seem
to be a problem (note the identical query plans):

ants=# EXPLAIN ANALYZE SELECT users.id, (SELECT COUNT(*) FROM
documents WHERE documents.user_id = users.id) AS doc_count FROM users
WHERE (SELECT COUNT(*) FROM documents WHERE documents.user_id =
users.id)  9;
   QUERY
PLAN
-
 Seq Scan on users  (cost=0.00..236010.06 rows=7000 width=4) (actual
time=0.066..190.913 rows=1883 loops=1)
   Filter: ((subplan)  9)
   SubPlan
 -  Aggregate  (cost=8.40..8.41 rows=1 width=0) (actual
time=0.007..0.007 rows=1 loops=21000)
   -  Index Scan using user_id_idx on documents
(cost=0.00..8.38 rows=7 width=0) (actual time=0.003..0.005 rows=5
loops=21000)
 Index Cond: (user_id = $0)
 -  Aggregate  (cost=8.40..8.41 rows=1 width=0) (actual
time=0.010..0.010 rows=1 loops=1883)
   -  Index Scan using user_id_idx on documents
(cost=0.00..8.38 rows=7 width=0) (actual time=0.003..0.007 rows=10
loops=1883)
 Index Cond: (user_id = $0)
 Total runtime: 191.296 ms
(10 rows)

ants=# EXPLAIN ANALYZE SELECT * FROM (SELECT users.id, (SELECT COUNT
(*) FROM documents WHERE documents.user_id = users.id) AS doc_count
FROM users) AS x WHERE x.doc_count  9;
   QUERY
PLAN
-
 Seq Scan on users  (cost=0.00..236010.06 rows=7000 width=4) (actual
time=0.064..191.524 rows=1883 loops=1)
   Filter: ((subplan)  9)
   SubPlan
 -  Aggregate  (cost=8.40..8.41 rows=1 width=0) (actual
time=0.007..0.007 rows=1 loops=21000)
   -  Index Scan using user_id_idx on documents
(cost=0.00..8.38 rows=7 width=0) (actual time=0.003..0.005 rows=5
loops=21000)
 Index Cond: (user_id = $0)
 -  Aggregate  (cost=8.40..8.41 rows=1 width=0) (actual
time=0.010..0.010 rows=1 loops=1883)
   -  Index Scan using user_id_idx on documents
(cost=0.00..8.38 rows=7 width=0) (actual time=0.003..0.007 rows=10
loops=1883)
 Index Cond: (user_id = $0)
 Total runtime: 191.931 ms
(10 rows)


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: SQLAlchemy as a FIFO buffer?

2009-06-29 Thread Ants Aasma

Depends on what kind of concurrency you are expecting. Simple answer
is to just lock the table for queue updates. Another option is to do
it with serializable transactions, but you'll have to handle
serialization errors, and your database will pretty much halt and
catch fire if you get heavy contention on queue removal.

Another way would be to build upon PgQ from the SkyTools package,
assuming Postgres is an option. This gets you high performance and
high concurrency with ACID reliability, but you'll have to handle the
annoying possibility of getting items multiple times.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: DB Redundancy

2009-05-08 Thread Ants Aasma

On May 7, 4:15 pm, goo...@venix.com goo...@venix.com wrote:
 MySQL has a mechanism for a database to read the log from a master
 database and replay the commands.  This provides a loose coupling with
 near real-time backup of the data.  Should the backup server stop or
 lose contact, the primary server is unaffected.  When the backup
 server regains contact, it restarts the log processing from the point
 where it left off.

MySQL log based replication is asynchronous. It's only useful if
losing some transactions in case of a crash isn't a problem.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: DB Redundancy

2009-05-06 Thread Ants Aasma

On May 6, 9:07 am, Vic vctr...@gmail.com wrote:
 I'm looking for a way to have my DB replicated in REAL TIME to be used
 in case I lose my primary copy.

 I saw that the two phase commit exist but I'm not sure if that is the
 correct option. I have the feeling that it would be abusing a
 mechanism purposed for correlating to separate DBs and not creating
 replications.

The preferred way to replicate databases is to use ready-made database
replication tools. For postgres the easiest way to do synchronous
replication is currently pgpool-II. With mysql I'm not so sure, there
is the NDB cluster, but it has its own issues, possibly you can find
similar replication middleware for it.

If you must do the replication inside your application, then my advice
is to do it by subclassing sqlalchemy.engine.{Engine,Connection} to
handle distributing requests to multiple backends and managing
transactions across them. You still need 2 phase commits to achieve
consistency, and the corresponding separate transaction management
that goes with it (to rollback/commit prepared transactions in case of
crashes). Also to avoid inconsitencies you have to get sequence values
from one database, and cannot use volatile functions for inserts,
updates. Also, if you are doing this to get high availability, then
you need figure out, how to bring a replica up online. Don't expect
this to be anything near simple or transparent if you want to have any
kind of concurrency for write queries.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: func keyword and pg scheme

2009-03-26 Thread Ants Aasma

On Mar 26, 5:24 pm, PD p...@dlabal.cz wrote:
 How can I use my own function located in scheme outside public?
 (PostgresSQL, SA 0.4.6)

func.schema.function()
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Querying many-to-many relations

2009-03-20 Thread Ants Aasma

On Mar 20, 12:54 pm, Marcin Krol mrk...@gmail.com wrote:
 However, I have a problem doing a query at SQLA level that will select
 email, hwrep name and project name. The simple SQL query is straightforward:

 select email.Email, project.Project, hwrep.HWRep from email, project,
 hwrep,  project_hwreps where hwrep.id = project_hwreps.HWRep_id and
 project.id = project_hwreps.Project_id and hwrep.Email_id = Email.id;

 I have tested that this query selects just what I want.

 However, I would like to be able to use SQLA query mech for this, but I
 have trouble constructing the query.

Try session.query(Email.Email, Project.Project, HWRep.HWRep).join
(HWRep.Projects, HWRep.Email)
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: getting referenced *class* from relation

2009-03-17 Thread Ants Aasma

On Mar 17, 12:17 am, Alessandro Dentella san...@e-den.it wrote:
   Now I want to get User class starting from Project and 'staff'.

   Project.__mapper__.get_property('manager')._get_target().class_

   seems to do that but the leading underscore in _get_target suggest it's
   private, so I wandererd if that's the best way...

Project.manager.property.mapper.class_
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Ordering results of a WHERE x in y query by y

2009-02-26 Thread Ants Aasma

import sqlalchemy

def index_in(col, valuelist):
return sqlalchemy.case([(value,idx) for idx,value in enumerate
(valuelist)], value=col)

session.query(C).filter(C.someattr.in_(valuelist)).order_by(index_in
(C.someattr, valuelist))

Don't try to do this with huge lists of items.

On Feb 25, 5:53 pm, Gunnlaugur Briem gunnlau...@gmail.com wrote:
 Hi all,

 having a x IN y query, with y supplied as input to the query:

     session.query(C).filter(C.someattr.in_(valuelist))

 is there a way to tell SQLAlchemy to order the results according to
 valuelist? I.e. not by the natural order of someattr, but by the
 arbitrary order seen in valuelist? E.g.:

 session.add(C(someattr='Abigail'))
 session.add(C(someattr='Benjamin'))
 session.add(C(someattr='Carl'))
 valuelist = ['Benjamin', 'Abigail']
 q = session.query(C).filter(C.someattr.in_(valuelist)).order_by(clever
 (valuelist))
 q.all()
 # returns [C('Benjamin'), C('Abigail')]

 The solution I can think of is to create a temporary table with
 sess.execute('create temp table ...'), insert the valuelist into that
 temp table along with a sequence index, join to that temporary table
 and order by its index. Is there a less kludgy way?

 Regards,

     - Gulli
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: A question about best practices after the Object Relational Tutorial

2009-02-17 Thread Ants Aasma

I have written a descriptor for implementing hashed storage of
passwords. I added some documentation and added it to the wiki as a
recipe:

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

It doesn't depend on anything in SQLAlchemy and works with any object
persistence framework. It could probably use some better null handling
and error reporting, but should be usable as is.

Ants
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Selecting what properties of an object will be loaded

2008-10-16 Thread Ants Aasma

With
session.query(User).options(undefer(User.column_a),
defer(User.column_b), noload(User.column_c))
column_a will be loaded with the query, column_b will be loaded on
access and column_c will be None regardless of the value in the
database.

Ants

On Oct 16, 12:56 pm, Alex K [EMAIL PROTECTED] wrote:
 Hi All,

 I wonder if there is a way to set what columns of the object will be
 used during this particular query, to reduce the query in case if I
 need the object, but I don't need all object properties.

 is something like this: session.query(User).load('column_a') possible?

 session.query([...]) - won't apply, since i need mapped object.

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



[sqlalchemy] Re: how to print a constructed query with it's parameters?

2008-10-15 Thread Ants Aasma

This seems to come up often. I took a few minutes and threw together a
semi-robust way to do this on 0.5 series. I posted it under usage
recipes in the wiki: http://www.sqlalchemy.org/trac/wiki/DebugInlineParams
It has some flaws, but should be somewhat helpful for debugging.

Ants

On Oct 15, 2:42 pm, alex bodnaru [EMAIL PROTECTED] wrote:
 hi friends,

 i have a lot to learn from both approaches, but i have sadly appeared too 
 lazy.

 there will be no problem to imagine what the sql will be, only by
 looking at the
 template statement (with ?'s) and at the list of parameters.

 since the template is available to print (probably by __str__), i'd
 onlu ask where
 the bindparams list is. eventual quotes and escapes may be imagined by
 the types of
 the columns.

 thanks in advance,
 alex

 On Wed, Oct 15, 2008 at 12:54,  [EMAIL PROTECTED] wrote:

  i have another approach, which may or may not serve you.
  All those '?' are bindparams, and one can eventualy get them printed
  with their names - and put names where there aren't.
  that's what i needed, i guess replacing names with values would be
  easy job.
  the code is part of tests/convertertest.py of sqlalchemyAggregator,
 http://dev.gafol.net/t/aggregator/
  or
 http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/agg...

  class T_mark( unittest.TestCase):
  ...
     def setUp( self):
         self.m = MetaData()
         #hack for better visibility
         def bp( self,bindparam):
             if bindparam.value is not None:
                return 'const('+repr(bindparam.value)+')'
             k = bindparam.key
             if k.startswith( Converter._pfx): #my own bindparams
                 k = k[ len( Converter._pfx):]
             return 'BindParam('+k+')'
         self.old_bp = DefaultCompiler._truncate_bindparam
         DefaultCompiler._truncate_bindparam = bp

     def tearDown( self):
         DefaultCompiler._truncate_bindparam = self.old_bp
  ...

  str(expression) then does things like
  :const(True) AND :BindParam(oid) = movies.id
  tags.tabl = :const('movies') AND tags.oid = :BindParam(oid)

  there's some more stuff going on there around compatibility with SA
  0.3--0.5, but that's core.

  ciao
  svil

  On Wednesday 15 October 2008 13:33:46 King Simon-NFHD78 wrote:
   -Original Message-
   From: sqlalchemy@googlegroups.com
   [mailto:[EMAIL PROTECTED] On Behalf Of alex bodnaru
   Sent: 15 October 2008 11:00
   To: SQLAlchemy
   Subject: [sqlalchemy] how to print a constructed query with
   it's parameters?

   hello friends,

   in order to debug my code, i wish to print my query sql.

   it's in the fashion of
   query =
   table.query().filter(table.code='XL').filter(table.name.like('
   %'+q+'%')
   with unicode parameters.

   by just printing query, i get the select with ? parameters, but
   not the additional parameters list, that contains ['XL',
   %q-value%]. since it doesn't presently work ok, i'd like to print
   the list as well.

   thanks in advance,
   alex

  This question comes up a lot. For example, see
 http://groups.google.com/group/sqlalchemy/browse_thread/thread/a060
 2ede8 18f55c7

  Firstly, if you use echo=True in your call to create_engine, all
  SQL will be printed to stdout. The parameters will be displayed as
  a list AFTER the SQL is printed.

  Eg. (fromhttp://www.sqlalchemy.org/docs/05/ormtutorial.html)

  BEGIN
  INSERT INTO users (name, fullname, password) VALUES (?, ?, ?)
  ['ed', 'Ed Jones', 'edspassword']
  SELECT users.id AS users_id, users.name AS users_name,
  users.fullname AS users_fullname, users.password AS users_password
  FROM users
  WHERE users.name = ?
  LIMIT 1 OFFSET 0
  ['ed']

  You can control the logging more finely using the logging module -
  see
 http://www.sqlalchemy.org/docs/05/dbengine.html#dbengine_logging
  for more details.

  The problem is that SQLAlchemy doesn't ever replace those '?'
  characters with the actual parameter values. Those strings are
  passed directly to the DBAPI driver, along with the list of
  parameter values. It is then up to the DBAPI driver how it passes
  the query to the database. (This is why SQLAlchemy is fairly safe
  from SQL Injection attacks).

  Hope that helps,

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



[sqlalchemy] Re: Random result

2008-08-25 Thread Ants Aasma

order by rand() doesn't scale too well unfortunately.
http://www.depesz.com/index.php/2007/09/16/my-thoughts-on-getting-random-row/
has some better approaches. It's postgres specific but the approach
should be generalizable by moving logic to client side.

On Aug 23, 8:30 pm, GustaV [EMAIL PROTECTED] wrote:
 Ok, I wanted to know if there was a way to do it with no database
 specific code.

 Then you are right :
 I'll first query the result count (unknown a priori) and then use a
 random python generated offset.

 If anyone has a better idea (in 1 request only), that would be great!

 On 23 août, 18:34, Michael Bayer [EMAIL PROTECTED] wrote:

  On Aug 23, 2008, at 12:10 PM, GustaV wrote:

   Hi all,
   Really, you do an amazing job on that stuff, it's a pleasure to work
   with!

   A short question though. It's possible to get a random order on
   selects in mysql using the RAND() in parameter of ORDER BY. I know
   similar (but different) was possible on others.
   What about sqlalchemy?
   The goal is to have only one result on the query, randomly.

  if the function is RAND(), you'd just say
  select.order_by(func.rand()).    If you're looking for just the first
  result then you'd use limit/offset (the select() and Query()
  constructs both support limit() and offset() methods for this).

  I'm not familiar with the random function of other databases but the
  same techniques apply.   SQLA could also could also support with a
  generic version of this function which calls the correct rand()
  function on each database, but only if very similar choices exist on
  most backends.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Exclude Autogenerated Timestamp Column

2008-01-12 Thread Ants Aasma

On Jan 12, 4:43 am, Rick Morrison [EMAIL PROTECTED] wrote:
 My experience with GUID PKs is that they almost always cause more troubles
 than they purport to solve, and 99% of the time a plain Integer PK will work
 just fine instead. The two rare exceptions are with multi-database
 synchronization (and even there integer PKs can work fine with an additional
 'source' discriminator column) and humungo databases where overflowing a
 bigint col is a real fear.

A bit offtopic, but I can't imagine a situation where overflowing a
bigint col would
be feasible. Even if you generate 1 billion rows per second, you still
have about
300 years worth of keys available.

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



[sqlalchemy] Re: rlike with assign_mapper?

2007-11-01 Thread Ants Aasma

To do this nicely ticket #767 would have to be fixed, but until then
this should work:
def rlike_match_all(entity, **kwargs):
return and_(*[getattr(entity,
key).comparator.expression_element().op('rlike')(value) for key,value
in kwargs.items()])

and use it by
Resource.select(rlike_match_all(Resource, query_dict))

Ants

So you can
On Nov 1, 8:12 pm, iain duncan [EMAIL PROTECTED] wrote:
 Others gave some pointers a while back on using rlike with query
 filters. I'm wondering whether there is some way to get rlike with
 assign_mapper syntax?

 I'm using right now

 Resource.select_by( **query_dict )

 where query dict is name/val pairs, I'd like to be able to make those
 name/val pairs be re matches. Any tips most appreciated!

 Thanks
 Iain


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



[sqlalchemy] Re: non-blocking row locks?

2007-10-03 Thread Ants Aasma

Coincidentally I had to implement almost exactly the same thing today.
I used separate job checkout/checkin transactions, serializable
isolation level to find out when there is a collision and job checkout
time to see which jobs are currently running. By default the checkout
time is a special date way in the past instead of NULL to make it work
better with indexing. This implements a kind of optimistic locking
that throws serialization errors when two workers checkout
concurrently. I'm hoping that this won't hit performance problems,
because the checkout process is quite fast compared to the processing,
although there will be around 40 workers running concurrently in the
cluster.

The code I used is basically this: (slightly edited to omit
confidential/superfluous stuff)

def check_out_dataset_for_processing():
for retries in xrange(MAX_RETRIES):
try:
session = Session()

# This is necessary to avoid duplicate checkouts
session.connection(Dataset).execute(SET TRANSACTION
ISOLATION LEVEL SERIALIZABLE)

# Database side CURRENT_TIMESTAMP would be a lot better
now = datetime.now()
timeout_horizon = now - timedelta(seconds=TIMEOUT)

dataset =
session.query(Dataset).filter_by(is_processed=False)\
.filter(Dataset.last_checkout 
timeout_horizon).first()

if dataset:
# If found something mark it checked out
dataset.last_checkout = now
result = dataset.id, dataset.data_for_processing
else:
result = None

session.commit()

return result
except sqlalchemy.exceptions.ProgrammingError, e:
if e.orig.pgcode != '40001': # Ignore serialization
conflicts
raise
logger.error('Failed to checkout a dataset')

def store_processing_result(dataset_id, processing_result):
session = Session()

dataset = session.query(Dataset).filter_by(id=dataset_id).first()

dataset.result = processing_result
dataset.is_processed = True

session.commit()

In my case duplicate execution is only a performance issue so when a
worker times out due to crashing or just being slow that dataset is
handed to another worker. Though this code can easily be modified to
do something different in case of timeout. I don't have a separate job
table and the datasets table is millions of rows so to get good
performance I used a partial index (currently only in trunk):

Index('unprocessed_datasets_idx', datasets.c.last_checkout,
postgres_where=datasets.c.is_processed == False)

This reduces the job lookup to a simple index lookup.


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



[sqlalchemy] Re: Mapping serial(auto increment) Postgres to bigserial

2007-10-02 Thread Ants Aasma

On Oct 2, 10:06 am, voltron [EMAIL PROTECTED] wrote:
 How does one specify that the auto incrementing field should map to
 big serial and not serial?
Use the sqlalchemy.databases.postgres.PGBigInteger datatype for that
field.


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



[sqlalchemy] Re: postgres POLYGON data type

2007-09-17 Thread Ants Aasma

On Sep 17, 3:03 pm, [EMAIL PROTECTED] wrote:
 Has anyone added support for the POLYGON data type in PostgreSQL? If
 so, is there any code that can be shared?

Here's a patch implementing PGPolygon. The conversion from/to python
types should be done in dbapi IMHO (i.e. psycopg2) but this will work
until it is.

Ants

PS: any idea why the google groups web api doesn't allow attaching of
files

Index: lib/sqlalchemy/databases/postgres.py
===
--- lib/sqlalchemy/databases/postgres.py(revision 3500)
+++ lib/sqlalchemy/databases/postgres.py(working copy)
@@ -140,6 +140,28 @@
 def get_col_spec(self):
 return self.item_type.get_col_spec() + '[]'

+class PGPolygon(sqltypes.TypeEngine):
+def dialect_imp(self, dialect):
+return self
+
+def bind_processor(self, dialect):
+def process(value):
+if value is None:
+return value
+return '(' + ','.join('(%G,%G)' % (x,y) for x,y in value)
+ ')'
+return process
+
+def result_processor(self, dialect):
+points = re.compile(r'\(([0-9.Ee]+),([0-9.Ee]+)\)')
+def process(value):
+if value is None:
+return value
+return tuple(map(lambda v:tuple(map(float, v)),
points.findall(value)))
+return process
+
+def get_col_spec(self):
+return POLYGON
+
 colspecs = {
 sqltypes.Integer : PGInteger,
 sqltypes.Smallinteger : PGSmallInteger,
@@ -177,6 +199,7 @@
 'bytea' : PGBinary,
 'boolean' : PGBoolean,
 'interval':PGInterval,
+'polygon': PGPolygon,
 }

 def descriptor():


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



[sqlalchemy] Re: relative insert performance

2007-07-11 Thread Ants Aasma

On Jul 11, 9:02 pm, Justus Pendleton [EMAIL PROTECTED] wrote:
 I've noticed some large (10x) performance differences between sqlalchemy (no
 ORM) and plain DB API when using sqlite and was wondering if that is
 something expected even when I'm (trying to) avoid the ORM stuff or if I'm
 just doing something wrong.

Looking at 
http://www.sqlalchemy.org/trac/attachment/wiki/ProfilingResults/sqla.insert.prof.png
this is in the ballpark of whats expected. You can about double your
performance by compiling the insert and using the result instead of
the insert clause. And if that is not enough you can buffer insertable
data into a list and execute many rows at a time, this should
dramatically decrease SQLAlchemy overhead.

Ants


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



[sqlalchemy] Re: pattern about nested transactions?

2007-05-24 Thread Ants Aasma

On May 23, 6:44 pm, Michael Bayer [EMAIL PROTECTED] wrote:
  add on top of this versioning/bitemporalism and things get tough...

 big words again...hold on...zero google hits for 'bitemporalism'...OK
 i guess that means two things happening at once

I think he means the distinction between actual time and record time
of temporal objects as nicely described by Fowler (http://
www.martinfowler.com/eaaDev/timeNarrative.html). I'm currently
developing an application that needs that distinction and I can say
that it can get pretty confusing at times.

  Any ideas/patterns how to transfer this nesting-of-user-transactions
  into DB / alchemy?

 I dont have a deep insight since i havent done persistent GUI stuff
 since the late 90s, but definitely dont use a real DB transaction for
 the dialog windows...you dont want any long-running DB transactions
 (but i think you knew that).

If you know really well what you're doing then it may be simpler to
offload all the lock management, transaction isolation and consistency
to the database. But as a rule of thumb, long-running transactions are
bad, mkay.

 the two options that come to mind, for the nested scenarios
 particularly, are using multiple Sessions / copies of the objects to
 keep their changes separate, and the other is to have a separate
 model configured for your GUI windows...probably a command pattern
 that encapsulates each click/state change in a distinct command
 instance (without modifying domain objects).  when youre ready to
 actually write to the database, you loop through your accumulated
 command objects and apply each change to the appropriate domain
 object and then flush() as approrpriate.

Actually unit of work can be regarded as a kind of command pattern. So
what could work here is nested units of work.


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



[sqlalchemy] Re: Column to default to itself

2007-04-13 Thread Ants Aasma

On Apr 13, 1:47 pm, Koen Bok [EMAIL PROTECTED] wrote:
 request_table = Table('request', metadata,
 Column('id', Integer, primary_key=True),
 Column('number', Integer, unique=True, nullable=True,
 default=text('(SELECT coalesce(max(number), 0) + 1 FROM 
 request)')))

 This seems to work well. But is  this a good way to do this or can it
 cause complications?

This will start to throw duplicate key errors under heavier load.
There is a window of time between insert and commit when another
insert will get the same duplicate id. It might not be a problem in
your case, but I have had to deal with a similar problem when creating
sequentally hashed database table (for provable temporal ordering and
integrity) which will see very high loads. You'll either occasionally
get duplicate values in the database or you have to serialize all
inserts. The best that can be done, is try to occasionally get holes
and assume that usually transactions succeed and catch rollbacks. That
is a lot harder.

Ants


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-13 Thread Ants Aasma

On Apr 13, 6:40 pm, Rick [EMAIL PROTECTED] wrote:
 Sorry, it looks like is already being discussed.  (Serve me right for
 reading in threaded mode.)  From my SA-newbie POV, I'd love it if
 col.in_() compiled down to false or 0 (whatever works).

col.in_() is easy to get working correctly, the problem is
not_(col.in_()). In order to be consistent with regular IN behaviour
this should only return rows with non null values. By example of mysql
(because it has the nicest display, others work the same):
mysql SELECT null IN (1,2,3), 0 IN (1,2,3), NOT null IN (1,2,3), NOT
0 IN (1,2,3)\G
*** 1. row ***
null IN (1,2,3): NULL
   0 IN (1,2,3): 0
NOT null IN (1,2,3): NULL
   NOT 0 IN (1,2,3): 1

To be locally consistent with this behaviour the expression should
return null when col is null, else return false. The case statement
mentioned before is actually the most straightforward encoding of this
behaviour. It is big only due to verbosity of SQL syntax. In Python it
would be None if col is None else False.


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-13 Thread Ants Aasma

On Apr 13, 10:16 pm, Michael Bayer [EMAIL PROTECTED] wrote:
 OK, first thing i wasnt sure about, is CASE supported on every DB
 that we support.  I took a look at our CASE unit test and it appears
 it applies to all DBs...(although i cant verify it passes on
 firebird).

Works on Firebird 1.5.3. I haven't verified older MySQL and PostreSQL
releases, but I'll try to verify those too, or at least check
changelogs for related changes.

 really, the work to do here is 5% the patch to the in_() method, and
 95% making me a really nice unit test suite that will generatively
 test IN for every contingencyincluding the bind param stuff in
 #476 (but simpler code than whats patched there).   otherwise its
 giong to sit in the queue for awhile since i still have a lot of
 other more pressing patches i havent yet had the time to test/apply.

I'll try to create a test suite for it next week, I have already
identified most of the test cases. Should I attach it to #476 or
create a new ticket?


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-12 Thread Ants Aasma

On Apr 12, 1:59 am, Michael Bayer [EMAIL PROTECTED] wrote:
 agreed, as long as we know that saying somecolumn != somecolumn is
 valid and produces False on all dbs (including frequent-offenders
 firebird and ms-sql) ?  (thats how you interpreted IN (), right ?)

It works (almost) ok in MSSQL-8, Sqlite-2/3, PostgreSQL 8.1/8.2, MySQL
5.0, Oracle 10g and Firebird 1.5.3. It works with literals, columns,
expressions, subselect expressions, no rows subselects in all of them.
It fails when the expression is a volatile function or a function with
side effects (e.g. func.random().in_()). The latter two cases will
work ok, if you compile it as ((CASE WHEN expr IS NULL THEN NULL ELSE
0 END) = 1)

Ants


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-12 Thread Ants Aasma

On Apr 12, 6:37 pm, svilen [EMAIL PROTECTED] wrote:
 how about whatever.in() - (whatever and False)
 maybe problem with Null then?
(null and false) gives false, so not(null and false) is true. This
means that not_(col.in_()) returns all rows, while
not_(col.in_(nonexistantvalue)) returns all that are not null. One
other option would be to return
_BooleanExpression(self._compare_self(), null(), '=', negate='IS
NOT'). The only problem is and edge case when someone uses an in_ with
an comparison expression like so: col.in_() == False. This should
return a list of non-null entries to be consistent, but instead
returns an empty list. IMHO the expected behaviour is quite clear in
all cases - just use the standard SQL idioms and relational idioms,
comparison with null is null and no value is in an empty list. The
CASE WHEN expr IS null THEN null ELSE false END expresses it quite
nicely. The comparison is there to satisfy Oracle Firebird and Mssql,
which don't like plain case expressions in where. I'd say that it
makes the API conceptually simpler by removing a special case at the
expense of some minor (compared to some other constructs that SA ORM
emits) confusion when deciphering produced SQL statements.


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



[sqlalchemy] Re: Column to default to itself

2007-04-12 Thread Ants Aasma

On Apr 13, 2:47 am, Jorge Godoy [EMAIL PROTECTED] wrote:
 IF you insist on doing that at your code, make the column UNIQUE (or a
 PK...) and write something like this pseudocode:

 def save_data():
 def insert_data():
try:
unique_column_value = get_max_from_unique_column
Class(unique_column_value + 1, 'other data')
except YourDBExceptionForConstraintViolation:
sleep(random.random())
insert_data()

 The 'sleep(random.random())' is there to avoid constant clashes and to
 be fair to all connections that are inserting data on your table.

To get an uninterrupted number sequence you need to serialize your
inserts to that specific entity, for which you basically need locking.
The quoted approach is optimistic locking, where you hope that no one
tries to insert another row between when you use the
get_max_from_unique_column and do the database commit, but are ready
to retry if that expectation fails. Another way would be to use
pessimistic locking, by doing the get_max_from_unique_column query
with lockmode='update'. Then any other thread trying to insert another
row while you're busy inserting yours will have to wait.


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-11 Thread Ants Aasma

On Apr 11, 6:05 pm, Rick Morrison [EMAIL PROTECTED] wrote:
 Most of the way it works is great:

  col.in_(v1, v2, v2)

COL IN (v1, v2, v3) col.in_(v1)

COL = v1

 but this one:

  col.in_()

COL IS NULL

 is a mapping I don't think
 is right. In our case, it caused an unexpected enormous table scan
 that loaded over 800MB of data and set our server to swapping.

I'd say this is a definite bug. The semantics of col.in_(list) should
be column value equals any of the values in the list. For an empty
list it should be a constant false, because no value exists in an
empty list, not even an missing value (null). What makes it a bit
tricky is the fact that for null values the result should actually
also be null. When straight .in_() is used it doesn't really matter,
but when the negation is used then it starts to matter. That's because
not_(col.in_()) should be the equivalent of COL IS NOT NULL. I think
the best way would be to compile it to COL != COL, it has the correct
behaviour when negated as well as not negated. Diff follows:
Index: lib/sqlalchemy/sql.py
===
--- lib/sqlalchemy/sql.py   (revision 2494)
+++ lib/sqlalchemy/sql.py   (working copy)
@@ -895,5 +895,5 @@
 def in_(self, *other):
 if len(other) == 0:
-return self.__eq__(None)
+return self.__ne__(self)
 elif len(other) == 1 and not hasattr(other[0],
'_selectable'):
 return self.__eq__(other[0])


Ants


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



[sqlalchemy] Re: IN() bug bit hard

2007-04-11 Thread Ants Aasma

On Apr 11, 11:55 pm, Michael Bayer [EMAIL PROTECTED] wrote:
 but why dont we want to just have it compile just as it says - to IN
 () on the database side ?  im not sure if trying to guess what the
 user means here is the best approach (refuse the temptation to guess...)

Because that is not valid SQL. AFAIK the only database that implements
it is Sqlite and there it behaves exactly as expr != expr. It's quite
probable that users will try to use empty .in_(). The options are:
a) immediately  raise an error
+ errors are easy(er) to find
- invalidates sqlite behaviour
b) produce IN () SQL
+ 1:1 mapping between python and sql
- most databases will give obscure errors, possibly far away from
source of error
- different behaviour between databases
c) do a natural extension of SQL IN syntax
+ makes user code simpler in non negligible amount of cases
+ behaves the same in all databases
- some one could possibly expect different semantics

Did I miss anything?


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