[sqlalchemy] Re: A question about the Hybrid Value pattern for encrypted values

2011-06-22 Thread Roy Hyunjin Han
  In my case, I want to enforce case-insensitive comparison for
  encrypted email addresses.

 The hybrid can be made to work for encryption very nicely if you use a 
 comparator that coerces the value to its encrypted form before passing to the 
 database.   It's worth publishing so I created an example at 
 http://www.sqlalchemy.org/trac/wiki/UsageRecipes/SymmetricEncryption.

 The issue the approach has however is if you're dealing with salted 
 encryption and attempting to compare crypted values in the database - you 
 can't encrypt on the Python side since each comparison would require the salt 
 of each value to be compared.   Ants' older recipe at 
 http://www.sqlalchemy.org/trac/wiki/UsageRecipes/HashPropertyproposes using 
 DB side functions for this scenario.

Thanks so much for your advice.  I took your SymmetricEncryption
recipe and modified it to support case-insensitive comparison on the
encrypted values.  I created a working example below as a reference
for others.


from sqlalchemy import create_engine, func, Column, Integer,
LargeBinary
from sqlalchemy.ext.hybrid import hybrid_property, Comparator
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker


EMAIL_LEN_MAX = 256
encrypt = lambda x: x.encode('utf-8').replace('---', '===') # Dummy
function
decrypt = lambda x: x.decode('utf-8').replace('===', '---') # Dummy
function
db = scoped_session(sessionmaker())
Base = declarative_base()


class CaseInsensitiveUnicode(unicode): # !!!

def __lt__(self, other):
return self.lower()  other.lower()

def __le__(self, other):
return self.lower() = other.lower()

def __eq__(self, other):
return self.lower() == other.lower()

def __ne__(self, other):
return self.lower() != other.lower()

def __gt__(self, other):
return self.lower()  other.lower()

def __ge__(self, other):
return self.lower() = other.lower()


class CaseInsensitiveEncryptComparator(Comparator):

def operate(self, op, other, **kwargs):
return op(self.__clause_element__(), encrypt(other.lower()),
**kwargs) # !!!


class EmailMixin(object):
'Mixin class for a case-insensitive encrypted email address'
email_ = Column(LargeBinary(EMAIL_LEN_MAX * 2)) # Doubled for
unicode addresses
@hybrid_property
def email(self):
return CaseInsensitiveUnicode(decrypt(self.email_)) # !!!
@email.setter
def email(self, email):
self.email_ = encrypt(email.lower())
@email.comparator
def email(cls):
return CaseInsensitiveEncryptComparator(cls.email_)


class User(Base, EmailMixin):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)


engine = create_engine('sqlite:///', echo=True)
db.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)


db.merge(User(email='x...@example.com'))
db.merge(User(email='x...@example.com'))
user = db.query(User).filter_by(email='x...@example.com').first()
assert user.email == 'x...@example.com'
assert user.email == 'x...@example.com'
emails = [x.email for x in db.query(User)]
assert sorted(emails) == ['x...@example.com', 'x...@example.com']
assert 'x...@example.com' in emails


# 
https://github.com/invisibleroads/invisibleroads-templates/blob/master/invisibleroads/paster_templates/core/+package+/models.py_tmpl

-- 
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] A question about the Hybrid Value pattern for encrypted values

2011-06-21 Thread Roy Hyunjin Han
Hi Michael,

In the documentation you state that the Hybrid Value pattern is useful
for encrypted values.
http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html
Is it possible for you to provide an example of the Hybrid Value
pattern as applied to encrypted values?

In my case, I want to enforce case-insensitive comparison for
encrypted email addresses.  The email addresses are currently
encrypted model-side by overriding TypeDecorator to encrypt on the way
in and decrypt on the way out.

I have tried applying a
column_property(comparator_factory=CaseInsensitiveComparator) but that
applies lower() to the encrypted value instead of the decrypted email
address.

I thought the Hybrid Value pattern might apply in this case, but the
encrypt() and decrypt() functions I am using are strictly Python
without SQL equivalents.  Is there a way to enforce case-insensitive
encrypted comparison from the model?

Thanks,
RHH

-- 
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 the Hybrid Value pattern for encrypted values

2011-06-21 Thread Roy Hyunjin Han
On Jun 21, 5:55 pm, Roy Hyunjin Han starsareblueandfara...@gmail.com
wrote:
 In the documentation you state that the Hybrid Value pattern is useful
 for encrypted values.http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html
 Is it possible for you to provide an example of the Hybrid Value
 pattern as applied to encrypted values?

 In my case, I want to enforce case-insensitive comparison for
 encrypted email addresses.  The email addresses are currently
 encrypted model-side by overriding TypeDecorator to encrypt on the way
 in and decrypt on the way out.

 I have tried applying a
 column_property(comparator_factory=CaseInsensitiveComparator) but that
 applies lower() to the encrypted value instead of the decrypted email
 address.

 I thought the Hybrid Value pattern might apply in this case, but the
 encrypt() and decrypt() functions I am using are strictly Python
 without SQL equivalents.  Is there a way to enforce case-insensitive
 encrypted comparison from the model?

To answer my own question, I am going to guess that the Hybrid Value
pattern for encrypted values refers specifically to database-provided
encryption functions such as pgcrypto.  If the encryption functions
are pure Python, I don't think the Hybrid Value pattern applies.

-- 
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] How do we retrieve the database dialect that a specific session is using?

2010-04-24 Thread Roy Hyunjin Han
Is there any way to retrieve the database dialect that a specific
session is using?  e.g. MySQL, PostGIS, etc.

I am trying to modify Sanjiv Singh's GeoAlchemy extension so that a
person can retrieve the appropriate database procedure for a given
dialect, so that geospatial queries can be both direct (performed in a
single database call) as well as dialect-neutral.

For example, in PostGIS, getting the WKT of a geometry requires func.ST_AsText()
session.query(func.ST_AsText(Road.geom)).first()

However, in MySQL, the same procedure requires func.AsText()
session.query(func.AsText(Road.geom)).first()

I would like to be able to create a function called wkt() in both
geoalchemy/mysql.py and geoalchemy/postgis.py that enables me to the
following:
session.query(session.dialect.wkt(Road.geom)).first()

Thanks,
Roy Hyunjin Han
Modi Research Group
Earth Institute at Columbia University
http://modi.mech.columbia.edu

-- 
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: How to get inserted ids after row insert?

2009-07-14 Thread Roy Hyunjin Han

Hi Michael,

Does the behavior of result.lastrowid change after SQLAlchemy version
5.5?  It seems that in older versions lastrowid is the first id
inserted and in later versions lastrowid is the last id inserted.

RHH

On Fri, Apr 10, 2009 at 11:57 AM, Michael Bayermike...@zzzcomputing.com wrote:



 call result.lastrowid.  you'll get whatever the DBAPI deems worthy of
 sending.


 Andrija Frincic aka BobRock wrote:

 Hi all
 I use insert statement as text to insert record into MySQL DB. I chose
 this method because I use INSERT in combination with SELECT, so there
 is no way to use SQL Expression language. My problem is that there is
 no inserted ids available after inserting data using raw SQL
 statement. When I call last_inserted_ids on ResultProxy returned by
 session.execute I get following exception:
 AttributeError: 'MySQLExecutionContext' object has no attribute
 '_last_inserted_ids'.
 Here is a sample code:
 ins = insert into visitor(queueid, firstname, uid, added,
 description, queue_pos
 select :queueid, :firstname, :uid, :added, :description, max(queue_pos)
 +1 FROM visitor WHERE DATE(added)=DATE(:added) AND queueid=:queueid
 res = meta.Session.execute(ins, self.form_result);
 meta.Session.commit()
 ids = res.last_inserted_ids();

 I use SQL alchemy 0.5.2 with Pylons and with MySQLDb 1.2.3b1 and
 Python 2.6. Could someone point me how to get id of inserted  record.

 Best regards
 Andrija

 



 


--~--~-~--~~~---~--~~
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: connectionless queries with Spatial data (PostGIS)

2009-04-20 Thread Roy Hyunjin Han

 Geospatial support is definitely an external project in any case.
 As soon as something goes in the core, it's now
 linked to our release process, I'm getting the tickets and complaints
 personally, etc., theres no way a huge subject like geo support
 belongs there.

I agree with you that it has to be an external project.  I do not want
to bog down SQLAlchemy's release process.


 I'm just looking for smooth integration with PostGIS
 and other geospatial SQL extensions.If we decide my observation
 that GeoDjango has done a lot of work that needs to be re-done isn't
 really valid, and everything they've done is only useful for Django
 web applications, then that idea should be scrapped, and a simple
 library which builds upon SQLAlchemy expression constructs should be
 created.

We need the SQLAlchemy extension to Spatialite in the lab now, so
we'll get to work on that first.

1. As you suggested, we'll first try looking into making GeoDjango
work as a plugin, in which case we'll get a lot of stuff for free.
2. Otherwise, we'll write our own stripped-down version for Spatialite
and PostGIS.

I'm aiming for a release of the plugin or extension by the end of May.

--~--~-~--~~~---~--~~
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: connectionless queries with Spatial data (PostGIS)

2009-04-19 Thread Roy Hyunjin Han

Michael,

Do you know if anyone is working on a PostGIS extension for
SQLAlchemy?  If not, I'd like to take a crack at it.

RHH


On Mon, Mar 16, 2009 at 1:47 PM, Michael Bayer mike...@zzzcomputing.com wrote:

 Roy H. Han wrote:

 On Feb 20, 6:52 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 Also I've built an ORM extension forpostgiswhich is incomplete but
 demonstrates how to round trip and createPostGISexpressions in a
 clean way, thats in the distribution in examples/postgis/postgis.py .


 Thanks for this contribution, Michael.  Will you be at the PyCon
 SQLAlchemy sprint?  I would like to work on getting PostGIS support
 hardcoded in the trunk.


 ill be there monday and tuesday.   PostGIS is a PG extension though so
 support for it should remain separateid most like an external tool
 along the lines of geodjango.



--~--~-~--~~~---~--~~
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: connectionless queries with Spatial data (PostGIS)

2009-04-19 Thread Roy Hyunjin Han

 Do you know if anyone is working on a PostGIS extension for
 SQLAlchemy?  If not, I'd like to take a crack at it.

 My suggestions regarding this are of course building off of the
 postgis.py example, and also perhaps, if its feasable (not sure if it
 is), building the whole thing as a plugin to GeoDjango, which works
 with many different databases besides Postgres, and seems to have a
 lot of non-django-specific functionality.   If the Django ORM bindings
 in GeoDjango could be replaced with SQLAlchemy bindings in an
 efficient way (where effiicient means, we're not taking Django ORM
 constructs and then translating to SQLA), we could leverage all the
 work they've done.


Hmm.  I was hoping I could add geospatial support to SQLAlchemy itself
rather than for a specific web framework.

I think GeoDjango wraps the geospatial C++ libraries (GDAL, GEOS,
PROJ) with PostGIS but otherwise most of the core functionality seems
to be in the geospatial C++ libraries.

I have also been tinkering with Alessandro Furieri's Spatialite for
SQLite3 and I think it would be a real boon if one could add
geospatial support to SQLAlchemy via Spatialite as well as PostGIS.

You are saying that we can save work by writing it as a plugin to
GeoDjango, but I really like Pylons.  Certainly, I can start with the
postgis.py example and use the GeoDjango API and MapFish API as
references.  The MapFish community seems to have integrated PostGIS
with Pylons already and maybe I can ask them how they feel about a
geospatial extension for SQLAlchemy?

We have a need for this at the lab because most of our custom desktop
GIS applications use SQLite and SQLAlchemy seems like a great way to
glue them all together.

--~--~-~--~~~---~--~~
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] PostgreSQL executemany and result.last_inserted_ids()

2009-04-09 Thread Roy Hyunjin Han

I'm trying to use SQLAlchemy's executemany syntax in PostgreSQL and
get the last_inserted_ids().
What is the recommended way to get these last_inserted_ids()?

I know that I can access the id attribute for each model instance but
there are hundreds of inserted rows and I would rather retrieve them
all at once.

Thanks,
RHH



 names = ['ted', 'steve', 'mike']

 result = meta.Session.execute(model.names_table.insert(), [{'name': x} for x 
 in names])

 result.last_inserted_ids()
Traceback (most recent call last):
  File 
/usr/lib/python2.5/site-packages/WebError-0.10.1-py2.5.egg/weberror/evalcontext.py,
line 35, in exec_expr
exec code in self.namespace, self.globs
  File web, line 1, in module
  File 
/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.2-py2.5.egg/sqlalchemy/engine/base.py,
line 1560, in last_inserted_ids
return self.context.last_inserted_ids()
  File 
/usr/lib/python2.5/site-packages/SQLAlchemy-0.5.2-py2.5.egg/sqlalchemy/engine/default.py,
line 284, in last_inserted_ids
return self._last_inserted_ids
AttributeError: 'PGExecutionContext' object has no attribute
'_last_inserted_ids'

--~--~-~--~~~---~--~~
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: PostgreSQL executemany and result.last_inserted_ids()

2009-04-09 Thread Roy Hyunjin Han

Yay!  I solved it.  Thanks for making such a great module.


 result = 
 meta.Session.execute(model.names_table.insert(postgres_returning=[model.names_table.c.id]),
  [{'name': x} for x in names])

 result.fetchall()
[(40,), (41,), (42,)]


On Thu, Apr 9, 2009 at 6:05 PM, Roy Hyunjin Han
starsareblueandfara...@gmail.com wrote:
 I'm trying to use SQLAlchemy's executemany syntax in PostgreSQL and
 get the last_inserted_ids().
 What is the recommended way to get these last_inserted_ids()?

 I know that I can access the id attribute for each model instance but
 there are hundreds of inserted rows and I would rather retrieve them
 all at once.

 Thanks,
 RHH



 names = ['ted', 'steve', 'mike']

 result = meta.Session.execute(model.names_table.insert(), [{'name': x} for 
 x in names])

 result.last_inserted_ids()
 Traceback (most recent call last):
  File 
 /usr/lib/python2.5/site-packages/WebError-0.10.1-py2.5.egg/weberror/evalcontext.py,
 line 35, in exec_expr
    exec code in self.namespace, self.globs
  File web, line 1, in module
  File 
 /usr/lib/python2.5/site-packages/SQLAlchemy-0.5.2-py2.5.egg/sqlalchemy/engine/base.py,
 line 1560, in last_inserted_ids
    return self.context.last_inserted_ids()
  File 
 /usr/lib/python2.5/site-packages/SQLAlchemy-0.5.2-py2.5.egg/sqlalchemy/engine/default.py,
 line 284, in last_inserted_ids
    return self._last_inserted_ids
 AttributeError: 'PGExecutionContext' object has no attribute
 '_last_inserted_ids'


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