[sqlalchemy] Adding order_by, offset and limit support to Delete

2010-12-22 Thread Tarek Ziadé
Hello,

I need to add order_by, limit and offset support to Delete objects for
MySQL. Here's what I've done so far, which works. See the long paste
below, I use delete() on my tables.

I would like to know if this is the right way to do things, or if I am
missing something. I am currently using 0.6.x

Thanks !

Tarek


from sqlalchemy.sql.expression import _generative, Delete, _clone, ClauseList
from sqlalchemy import util
from sqlalchemy.sql.compiler import SQLCompiler

class CustomCompiler(SQLCompiler):

def visit_delete(self, delete_stmt):
self.stack.append({'from': set([delete_stmt.table])})
self.isdelete = True

text = DELETE FROM  + self.preparer.format_table(delete_stmt.table)

if delete_stmt._returning:
self.returning = delete_stmt._returning
if self.returning_precedes_values:
text +=   + self.returning_clause(delete_stmt,
delete_stmt._returning)

if delete_stmt._whereclause is not None:
text +=  WHERE  + self.process(delete_stmt._whereclause)

if len(delete_stmt._order_by_clause)  0:
text +=  ORDER BY  + self.process(delete_stmt._order_by_clause)

if delete_stmt._limit is not None or delete_stmt._offset is not None:
text += self.limit_clause(delete_stmt)

if self.returning and not self.returning_precedes_values:
text +=   + self.returning_clause(delete_stmt,
delete_stmt._returning)

self.stack.pop(-1)

return text


class DeleteOrderBy(Delete):

def __init__(self, table, whereclause, bind=None, returning=None,
 order_by=None, limit=None, offset=None, **kwargs):
Delete.__init__(self, table, whereclause, bind, returning, **kwargs)
self._order_by_clause = ClauseList(*util.to_list(order_by) or [])
self._limit = limit
self._offset = offset

@_generative
def order_by(self, *clauses):
self.append_order_by(*clauses)

def append_order_by(self, *clauses):
if len(clauses) == 1 and clauses[0] is None:
self._order_by_clause = ClauseList()
else:
if getattr(self, '_order_by_clause', None) is not None:
clauses = list(self._order_by_clause) + list(clauses)
self._order_by_clause = ClauseList(*clauses)

@_generative
def limit(self, limit):
self._limit = limit

@_generative
def offset(self, offset):
self._offset = offset

def _copy_internals(self, clone=_clone):
self._whereclause = clone(self._whereclause)
for attr in ('_order_by_clause',):
if getattr(self, attr) is not None:
setattr(self, attr, clone(getattr(self, attr)))

def get_children(self, column_collections=True, **kwargs):
children = Delete.get_children(column_collections, **kwargs)
return children + [self._order_by_clause]

def _compiler(self, dialect, **kw):
return CustomCompiler(dialect, self, **kw)


def delete(table, whereclause = None, **kwargs):
return DeleteOrderBy(table, whereclause, **kwargs)



-- 
Tarek Ziadé | http://ziade.org

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



Re: [sqlalchemy] Adding order_by, offset and limit support to Delete

2010-12-22 Thread Michael Bayer
The general idea is great though you probably want to use the @compiles 
decorator to link the compile function to the expression element, since that's 
the API point of extension - that would remove the need for the _compiler() 
call:

http://www.sqlalchemy.org/docs/core/compiler.html?highlight=compiles

You probably don't need the _copy_internals() call either since 
insert/update/delete expressions aren't generally used with clause adaption 
(for a description of what that's all about, see 
http://techspot.zzzeek.org/2008/01/23/expression-transformations/ ).



On Dec 22, 2010, at 8:51 AM, Tarek Ziadé wrote:

 Hello,
 
 I need to add order_by, limit and offset support to Delete objects for
 MySQL. Here's what I've done so far, which works. See the long paste
 below, I use delete() on my tables.
 
 I would like to know if this is the right way to do things, or if I am
 missing something. I am currently using 0.6.x
 
 Thanks !
 
 Tarek
 
 
 from sqlalchemy.sql.expression import _generative, Delete, _clone, ClauseList
 from sqlalchemy import util
 from sqlalchemy.sql.compiler import SQLCompiler
 
 class CustomCompiler(SQLCompiler):
 
def visit_delete(self, delete_stmt):
self.stack.append({'from': set([delete_stmt.table])})
self.isdelete = True
 
text = DELETE FROM  + self.preparer.format_table(delete_stmt.table)
 
if delete_stmt._returning:
self.returning = delete_stmt._returning
if self.returning_precedes_values:
text +=   + self.returning_clause(delete_stmt,
 delete_stmt._returning)
 
if delete_stmt._whereclause is not None:
text +=  WHERE  + self.process(delete_stmt._whereclause)
 
if len(delete_stmt._order_by_clause)  0:
text +=  ORDER BY  + self.process(delete_stmt._order_by_clause)
 
if delete_stmt._limit is not None or delete_stmt._offset is not None:
text += self.limit_clause(delete_stmt)
 
if self.returning and not self.returning_precedes_values:
text +=   + self.returning_clause(delete_stmt,
 delete_stmt._returning)
 
self.stack.pop(-1)
 
return text
 
 
 class DeleteOrderBy(Delete):
 
def __init__(self, table, whereclause, bind=None, returning=None,
 order_by=None, limit=None, offset=None, **kwargs):
Delete.__init__(self, table, whereclause, bind, returning, **kwargs)
self._order_by_clause = ClauseList(*util.to_list(order_by) or [])
self._limit = limit
self._offset = offset
 
@_generative
def order_by(self, *clauses):
self.append_order_by(*clauses)
 
def append_order_by(self, *clauses):
if len(clauses) == 1 and clauses[0] is None:
self._order_by_clause = ClauseList()
else:
if getattr(self, '_order_by_clause', None) is not None:
clauses = list(self._order_by_clause) + list(clauses)
self._order_by_clause = ClauseList(*clauses)
 
@_generative
def limit(self, limit):
self._limit = limit
 
@_generative
def offset(self, offset):
self._offset = offset
 
def _copy_internals(self, clone=_clone):
self._whereclause = clone(self._whereclause)
for attr in ('_order_by_clause',):
if getattr(self, attr) is not None:
setattr(self, attr, clone(getattr(self, attr)))
 
def get_children(self, column_collections=True, **kwargs):
children = Delete.get_children(column_collections, **kwargs)
return children + [self._order_by_clause]
 
def _compiler(self, dialect, **kw):
return CustomCompiler(dialect, self, **kw)
 
 
 def delete(table, whereclause = None, **kwargs):
return DeleteOrderBy(table, whereclause, **kwargs)
 
 
 
 -- 
 Tarek Ziadé | http://ziade.org
 
 -- 
 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.
 

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