Re: [sqlalchemy] get to dialect specific column type

2010-09-22 Thread werner

 I tried with a hack to get to this, but still no luck.

I am doing:

from sqlalchemy.dialects.firebird import dialect
...
fbDialect = dialect()

...
if str(col.type) == 'DATETIME':
print col.type.dialect_impl(fbDialect)
print col.type.get_dbapi_type(fbDialect)

The first one gives me DATETIME and the second throws this exception.

Traceback (most recent call last):
  File saCreateDb.py, line 5, in module
import model as db
  File C:\dev\aaTests\sqla\i18nFB\model.py, line 116, in module
class Country_LV(Base):
  File C:\dev\aaTests\sqla\i18nFB\model.py, line 117, in Country_LV
__table__ = sautils.make_localize_view(Country(), Country_L(), 
Language(), metadata)
  File C:\dev\aaTests\sqla\i18nFB\sautils.py, line 181, in 
make_localize_view
storedProc = doCreateLocaleStoredProc(baseinst, baseTable, 
localeTable, localeLangCol, localeFK, procName)
  File C:\dev\aaTests\sqla\i18nFB\sautils.py, line 31, in 
doCreateLocaleStoredProc

print col.type.get_dbapi_type(fbDialect)
  File 
c:\python26\lib\site-packages\sqlalchemy-0.6.4-py2.6.egg\sqlalchemy\types.py, 
line 1191, in get_dbapi_type

return dbapi.DATETIME
AttributeError: 'FBDialect_kinterbasdb' object has no attribute 'DATETIME'

What am I doing wrong here?  And is there a cleaner way of doing this, 
i.e. get the dialect currently used instead of using a hard coded dialect.


On 20/09/2010 23:52, werner wrote:
I am trying to automatically generate the stored procedure I need for 
the localize stuff.


So, would like to do something like this:

aninst.__table__.c['created_at'].type.get_dbapi_type(dbapi) - to get 
e.g. TIMESTAMP for a DateTime column with Firebird SQL.


What is the most efficient/easy way to get at dbapi from e.g. an 
instance?


Isn't there some more elegant way then doing 
connection.engine.dialect.dbapi?


Werner






--
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] declarative - automatically add a primary key if the table doesn't have one

2010-09-22 Thread Yap Sok Ann
This is related to topic need 0.6_beta2-compat declarative meta
http://groups.google.com/group/sqlalchemy/browse_thread/thread/ae7cb9d2ab0b9cca

Prior to version 0.6, I use the following code to automatically add a
primary key if the table doesn't have one defined:

from sqlalchemy.ext.declarative import declarative_base,
DeclarativeMeta
from sqlalchemy.schema import Column
from sqlalchemy.types import Integer

class Meta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
for attr in dict_.itervalues():
if isinstance(attr, Column) and attr.primary_key:
break
else:
dict_['id'] = Column(Integer, primary_key=True)
return super(Meta, cls).__init__(classname, bases, dict_)

Base = declarative_base(metaclass=Meta)

Of course, that doesn't work anymore in 0.6. The suggestion from the
aforementioned threads is to replace:

dict_['id'] = Column(Integer, primary_key=True)

with

cls.id = Column(Integer, primary_key=True)

Unfortunately, that alone doesn't work in this case. The problem is
that the Base class itself will be the first one to go through the
Meta.__init__() method, so the whole thing essentially becomes:

Base.id = Column(Integer, primary_key=True)

For it to work, I have to wrap the code in an if-block, i.e.

class Meta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
if classname != 'Base':
for attr in dict_.itervalues():
if isinstance(attr, Column) and attr.primary_key:
break
else:
cls.id = Column(Integer, primary_key=True)
return super(Meta, cls).__init__(classname, bases, dict_)

which looks rather ugly. Is there a cleaner way to achieve this?

-- 
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] Empty a record

2010-09-22 Thread Michael Bayer

On Sep 21, 2010, at 11:51 PM, Michael Hipp wrote:

 On 9/21/2010 8:17 PM, Michael Bayer wrote:
 It definitely does not attempt an INSERT if id_ is set to a non-None value, 
 assuming that row already exists in the DB, without something else in your 
 model/usage causing that to happen.If id_ is None or the given id_ 
 doesn't exist in the DB, you get an INSERT.   auct_id has no direct effect 
 here.
 
 that also makes no sense since if you set auct_id manually, assuming 
 old.auct_id is not None, it wouldn't be None in the UPDATE statement.
 
 These behaviors (opposite what we expect) are what I'm indeed seeing.
 
 As usual, distilling down the behavior that appears wrong into a single file
 
 Attached.
 
 I'll be thrilled if you can figure out what really stupid thing I'm doing to 
 cause this.
 
 As always, many thanks for your help.

So here, the value of None for car.auction, merges into the session which 
becomes a pending change.   The flush overwrites car.auct_id with None because 
car.auction has been set to None.

The merge() process takes everything that is present on the incoming object and 
assigns it to the object that's in the session.  So here when merge sets 
old.auction = None, this is the effect.

So you want to merge an object where every attribute is either exactly the 
value that you want it to be, or it is not loaded or assigned to in any way 
(i.e. not present in __dict__).   If you pop auction from __dict__ before the 
merge, or just don't assign to auction in the contructor of Car and also dont 
issue a print car.auction later on, the program succeeds.

So for example, this works:

new = Car()  
new.id_ = old.id_ 
new.lane = old.lane  
new = sess.merge(new)
sess.commit()

if you took the None assignments out of the constructor, all you need is id_ 
and leave everything else untouched, and it succeeds.

So the other thing, with the INSERT, you need to look at stack traces when 
these things happen:

File empty.py, line 72, in module
new = sess.merge(new)
File sqlalchemy/orm/session.py, line 1165, in merge
self._autoflush()
File sqlalchemy/orm/session.py, line 863, in _autoflush

anytime you see _autoflush in a stack trace, that means that some state is in 
the session that you don't want it to be, and _autoflush is trying to push it 
out before its ready.   That a car row is being INSERTed during autoflush, 
means that a Car object has been added to the session.   The first thing you do 
is then ask new in sess to see if that's the case.

Here, the issue is that you're mixing the usage of merge() with the usage of 
objects that are already in the session.   new is added to the session via 
cascade:

new = Car()
new.id_ = old.id_
new.lane = old.lane
new.auct_id = old.auct_id
new.auction = old.auction
assert new in sess   # passes

The ways to get around that effect are:

- pass cascade=None to your 'cars' backref - this means, when you set 
somecar.auction = someauction, someauction is already in the session, 'somecar' 
doesn't get added automatically.   cascade also affects what merge() does along 
relationships so when changing this make sure it has the cascades that you 
still want.
- expunge new before you merge() it, but that's kind of messy.
- don't set any relationships that are going to cascade it into the session 

I think the general rule is to compose the object for merge() carefully so that 
it only contains what state you want to be merged.   None counts as state.

I definitely want to add a note about what the state of the given instance is 
copied means, regarding things in __dict__.





 
 Michael
 
 -- 
 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.
 
 empty.py

-- 
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] declarative - automatically add a primary key if the table doesn't have one

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 4:30 AM, Yap Sok Ann wrote:

 This is related to topic need 0.6_beta2-compat declarative meta
 http://groups.google.com/group/sqlalchemy/browse_thread/thread/ae7cb9d2ab0b9cca
 
 Prior to version 0.6, I use the following code to automatically add a
 primary key if the table doesn't have one defined:
 
 from sqlalchemy.ext.declarative import declarative_base,
 DeclarativeMeta
 from sqlalchemy.schema import Column
 from sqlalchemy.types import Integer
 
 class Meta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
for attr in dict_.itervalues():
if isinstance(attr, Column) and attr.primary_key:
break
else:
dict_['id'] = Column(Integer, primary_key=True)
return super(Meta, cls).__init__(classname, bases, dict_)
 
 Base = declarative_base(metaclass=Meta)
 
 Of course, that doesn't work anymore in 0.6. The suggestion from the
 aforementioned threads is to replace:
 
 dict_['id'] = Column(Integer, primary_key=True)
 
 with
 
 cls.id = Column(Integer, primary_key=True)
 
 Unfortunately, that alone doesn't work in this case. The problem is
 that the Base class itself will be the first one to go through the
 Meta.__init__() method, so the whole thing essentially becomes:
 
 Base.id = Column(Integer, primary_key=True)
 
 For it to work, I have to wrap the code in an if-block, i.e.
 
 class Meta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
if classname != 'Base':
for attr in dict_.itervalues():
if isinstance(attr, Column) and attr.primary_key:
break
else:
cls.id = Column(Integer, primary_key=True)
return super(Meta, cls).__init__(classname, bases, dict_)
 
 which looks rather ugly. Is there a cleaner way to achieve this?

I didn't think metaclasses were supposed to be pretty ?Checking that you're 
not the base is pretty standard metaclass stuff.  If the hardcoded name 
is the issue, you can look in bases:

if object not in bases:
 
or something more generic:

for k in cls.__mro__[1:]:
if isinstance(k, Meta):
# you're a Base subclass



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



Re: [sqlalchemy] get to dialect specific column type

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 3:06 AM, werner wrote:

 I tried with a hack to get to this, but still no luck.
 
 I am doing:
 
 from sqlalchemy.dialects.firebird import dialect
 ...
fbDialect = dialect()
 
 ...
if str(col.type) == 'DATETIME':
print col.type.dialect_impl(fbDialect)
print col.type.get_dbapi_type(fbDialect)
 
 The first one gives me DATETIME and the second throws this exception.
 
 Traceback (most recent call last):
  File saCreateDb.py, line 5, in module
import model as db
  File C:\dev\aaTests\sqla\i18nFB\model.py, line 116, in module
class Country_LV(Base):
  File C:\dev\aaTests\sqla\i18nFB\model.py, line 117, in Country_LV
__table__ = sautils.make_localize_view(Country(), Country_L(), Language(), 
 metadata)
  File C:\dev\aaTests\sqla\i18nFB\sautils.py, line 181, in make_localize_view
storedProc = doCreateLocaleStoredProc(baseinst, baseTable, localeTable, 
 localeLangCol, localeFK, procName)
  File C:\dev\aaTests\sqla\i18nFB\sautils.py, line 31, in 
 doCreateLocaleStoredProc
print col.type.get_dbapi_type(fbDialect)
  File 
 c:\python26\lib\site-packages\sqlalchemy-0.6.4-py2.6.egg\sqlalchemy\types.py,
  line 1191, in get_dbapi_type
return dbapi.DATETIME
 AttributeError: 'FBDialect_kinterbasdb' object has no attribute 'DATETIME'
 
 What am I doing wrong here?  And is there a cleaner way of doing this, i.e. 
 get the dialect currently used instead of using a hard coded dialect.
 
 On 20/09/2010 23:52, werner wrote:
 I am trying to automatically generate the stored procedure I need for the 
 localize stuff.
 
 So, would like to do something like this:
 
 aninst.__table__.c['created_at'].type.get_dbapi_type(dbapi) - to get e.g. 
 TIMESTAMP for a DateTime column with Firebird SQL.


what is the piece of information you ultimately want ?   I'm not sure what you 
need the DBAPI type tokens for, unless you are working with the DBAPI's cursor 
object directly (in which case, you're working with the DBAPI 
already...dbapi.DATETIME ?  if you're generating a stored procedure you're 
already well within the realm of non-DB-agnostic).

 Isn't there some more elegant way then doing 
 connection.engine.dialect.dbapi?

there's import kintersbasdb 


-- 
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] get to dialect specific column type

2010-09-22 Thread werner

 I try to explain in more detail what I am trying to do.

class Country(Base, CreateUpdateMixin):
__tablename__ = u'countries'

id = sa.Column(sa.BigInteger(), sa.Sequence('countries_id'), 
primary_key=True, nullable=False)

name = sa.Column(sa.String(length=30, convert_unicode=False))
iso2 = sa.Column(sa.String(length=2, convert_unicode=False))
iso3 = sa.Column(sa.String(length=3, convert_unicode=False))
telcode = sa.Column(sa.SmallInteger())

__localize_columns__ = ['name', ]

class Country_L(Base):
__table__ = sautils.make_localize_table(Country, 'countries_l', 
Language, metadata)


language = sao.relation(Language, backref='country_l')
country = sao.relation(Country, backref='country_l')

class Country_LV(Base):
__table__ = sautils.make_localize_view(Country(), Country_L(), 
Language(), metadata)


Witin make_localize_view I need to generate a stored procedure which 
gets information such as columns etc from Country and Country_L , 
the generated code looks like this:


CREATE OR ALTER PROCEDURE countries_lp
returns (created_at DATE, updated_at TIMESTAMP, id BIGINT, name 
VARCHAR(30), iso2 VARCHAR(2), iso3 VARCHAR(3), telcode SMALLINT) as

declare variable locale_name VARCHAR(30);

begin
for select created_at, updated_at, id, name, iso2, iso3, telcode 
from countries

into :created_at, :updated_at, :id, :name, :iso2, :iso3, :telcode
do
begin
begin
locale_name = Null;

select name from countries_l
where :id = countries_l.fk_countries_id and
countries_l.fk_languages_code5 = rdb$get_context('USER_SESSION', 
'LANG_CODE')

into :name;
end
if (:locale_name is not Null) then
begin
name = :locale_name;
end

suspend;
end
end

part of the code to generate the above is the following:

for col in basetable.c:
if str(col.type) == 'DATETIME':
# hack as I can't figure out a nicer/cleaner way
colType = 'TIMESTAMP'

basetable = Country.__table__

 What I like to do is replace the check for DATETIME with 
similar/same code I assume meta.create_all(engine) is using to 
generate create table (can't yet figure out where/how this is all 
done) and ideally this should work not only for Firebird engine.


Hope this is clearer.

Thanks for looking at all this.
Werner

--
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] Empty a record

2010-09-22 Thread Michael Hipp

On 9/22/2010 10:27 AM, Michael Bayer wrote:

Michael, thanks so much for taking the time to compose a very thorough answer. 
If you could indulge a few clarifications/suggestions ...



So here, the value of None for car.auction, merges into the session which 
becomes a pending change.   The flush overwrites car.auct_id with None because 
car.auction has been set to None.

The merge() process takes everything that is present on the incoming object and 
assigns it to the object that's in the session.  So here when merge sets 
old.auction = None, this is the effect.

So you want to merge an object where every attribute is either exactly the value that you want it to be, or 
it is not loaded or assigned to in any way (i.e. not present in __dict__).   If you pop auction 
from __dict__ before the merge, or just don't assign to auction in the contructor of Car and also 
dont issue a print car.auction later on, the program succeeds.


I have been putting more and more things in the constructors for 2 reasons:

  1) It's really convenient esp in unit tests to be able to spec everything
 on 1 line when creating a lot of objects at once.

  2) It has always been good business in Python to make sure all
 instance vars are given a default value as early as possible.

But here, that harmless act of setting auction=None actually triggers things 
to happen that go considerably beyond my simplistic notion of just making sure 
things have a default value.


This is the 2nd time in as many days that I've been tripped-up by having things 
in the constructor that didn't *have* to be there. But only now am I coming to 
realize why.


Some explanation of or warning about this in the docs would seem appropriate. 
As I look over the declarative tutorial, it is somewhat implied that every 
column should be set in the constructor:

http://www.sqlalchemy.org/docs/orm/tutorial.html#creating-table-class-and-mapper-all-at-once-declaratively


Here, the issue is that you're mixing the usage of merge() with the usage of objects that 
are already in the session.   new is added to the session via cascade:

new = Car()
new.id_ = old.id_
new.lane = old.lane
new.auct_id = old.auct_id
new.auction = old.auction
assert new in sess   # passes

The ways to get around that effect are:

- pass cascade=None to your 'cars' backref - this means, when you set 
somecar.auction = someauction, someauction is already in the session, 'somecar' doesn't 
get added automatically.   cascade also affects what merge() does along relationships so 
when changing this make sure it has the cascades that you still want.
- expunge new before you merge() it, but that's kind of messy.
- don't set any relationships that are going to cascade it into the session


On that last note I found that if I do:
  new = Car()
  new.id_ = old.id_
  new = sess.merge(new)
  new.auction = old.auction  # do this *after* merge
  sess.commit()

This seems to work and avoids me having to deal with the cascade stuff (which I 
don't understand) just yet. Any worries with this approach?



I definitely want to add a note about what the state of the given instance is 
copied means, regarding things in __dict__.


Some explanation of how things get in __dict__ and what their presence there 
means would help us noobs.


Also, is it really a good idea to go hacking on __dict__ (e.g. popping things 
out as mentioned above)?


Again, thanks,
Michael

--
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] get to dialect specific column type

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 12:19 PM, werner wrote:

 Witin make_localize_view I need to generate a stored procedure which gets 
 information such as columns etc from Country and Country_L , the 
 generated code looks like this:
 
 CREATE OR ALTER PROCEDURE countries_lp
returns (created_at DATE, updated_at TIMESTAMP, id BIGINT, name 
 VARCHAR(30), iso2 VARCHAR(2), iso3 VARCHAR(3), telcode SMALLINT) as
declare variable locale_name VARCHAR(30);
 
begin
for select created_at, updated_at, id, name, iso2, iso3, telcode from 
 countries
into :created_at, :updated_at, :id, :name, :iso2, :iso3, :telcode
do
begin
begin
locale_name = Null;
 
select name from countries_l
where :id = countries_l.fk_countries_id and
countries_l.fk_languages_code5 = rdb$get_context('USER_SESSION', 
 'LANG_CODE')
into :name;
end
if (:locale_name is not Null) then
begin
name = :locale_name;
end
 
suspend;
end
end
 
 part of the code to generate the above is the following:
 
for col in basetable.c:
if str(col.type) == 'DATETIME':
# hack as I can't figure out a nicer/cleaner way
colType = 'TIMESTAMP'
 
 basetable = Country.__table__
 
 What I like to do is replace the check for DATETIME with similar/same code 
 I assume meta.create_all(engine) is using to generate create table (can't 
 yet figure out where/how this is all done) and ideally this should work not 
 only for Firebird engine.
 
 Hope this is clearer.

nothing to do with DBAPI or their types.  Call str(col.type) will give you its 
default compilation.   Call str(col.type.compile(dialect=firebird.dialect()) 
will give you whatever firebird does with those types.


-- 
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] Empty a record

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 12:21 PM, Michael Hipp wrote:

 
 On that last note I found that if I do:
 new = Car()
 new.id_ = old.id_
 new = sess.merge(new)
 new.auction = old.auction  # do this *after* merge
 sess.commit()
 
 This seems to work and avoids me having to deal with the cascade stuff (which 
 I don't understand) just yet. Any worries with this approach?

I'm only worried that you don't understand the cascade behavior.  It is this:

c = Car()
a = Auction()

session.add(a)

c is not in the session, a is.

c.auction = a

this assigns c.auction, and because you have auction.cars as a backref, it 
appends to the cars collection.  The same is if you said:

auction.cars.append(c)

So now, c is in the session, as is a.

auction.cars has a default cascade of save-update.   Anything appended to 
this list, gets added to the same session as that of auction.   That's cascade. 
 I'm adding an option to relationship, cascade_backrefs=False, which will  
prevent save-update cascade from firing off on a backref.

 
 I definitely want to add a note about what the state of the given instance 
 is copied means, regarding things in __dict__.
 
 Some explanation of how things get in __dict__ and what their presence there 
 means would help us noobs.

this is mentioned right near the start of the tutorial:

http://www.sqlalchemy.org/docs/orm/tutorial.html#setting-up-the-mapping

 str(ed_user.id)
'None'

any attribute accessed defaults to None.


 
 Also, is it really a good idea to go hacking on __dict__ (e.g. popping things 
 out as mentioned above)?

no.  use del obj.attribute instead.


-- 
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] Empty a record

2010-09-22 Thread Michael Bayer
here's your new section:

http://www.sqlalchemy.org/docs/orm/session.html#merge-tips



-- 
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] Change echo at will

2010-09-22 Thread Michael Hipp

On 8/26/2010 8:55 PM, Mike Conley wrote:

On Thu, Aug 26, 2010 at 4:21 PM, Michael Hipp mich...@hipp.com
mailto:mich...@hipp.com wrote:

Is there a way to set 'echo' at any time? Everything I can find sets it
when the engine is created and doesn't seem to change it afterward.

You can assign the engine.echo property to True or False any time after
creating the engine.


Is there something that would trigger this to be recognized?

In trying to use this to see the sql from a key piece of code it seems if I 
have to do the engine.echo=True well in advance of when I want it to start; and 
similarly I need to wait well after I want it to stop before I set it to False. 
Otherwise I miss stuff.


Thanks,
Michael

--
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] Empty a record

2010-09-22 Thread Michael Hipp

On 9/22/2010 11:21 AM, Michael Hipp wrote:


  new = Car()
  new.id_ = old.id_
  new = sess.merge(new)
  new.auction = old.auction # do this *after* merge
  sess.commit()

This seems to work and  ...


Bah. I spoke too soon - it just doesn't throw an exception. But without 
explicitly setting every field to its default value, the session thinks nothing 
has changed and the UPDATE leaves most of the fields untouched.


Anyway, it appears I need a new approach to empty/blank a record. Options I can 
think of are:


1) Find a dict of all the default values for every field and set them
   explicitly. Does SQLAlchemy have that somewhere?

2) What about an approach of forcing a DELETE, INSERT, COMMIT on the
   old/new objects. Like this:

session.begin(subtransactions=True)
id_ = old.id_ # grab important stuff from 'old'
auct = old.auction
session.delete(old)  # kill old
session.commit()

new = Car()
new.id_ = id_
new.auction = auct
new = session.merge(new)
session.commit()

But I'm worried about side effects and issues with the version_id_col.

Any thoughts appreciated...

Michael

--
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] Change echo at will

2010-09-22 Thread Michael Bayer
the logging level is checked on each new connection, so yes you can set echo at 
any time.


On Sep 22, 2010, at 4:46 PM, Michael Hipp wrote:

 On 8/26/2010 8:55 PM, Mike Conley wrote:
 On Thu, Aug 26, 2010 at 4:21 PM, Michael Hipp mich...@hipp.com
 mailto:mich...@hipp.com wrote:
 
Is there a way to set 'echo' at any time? Everything I can find sets it
when the engine is created and doesn't seem to change it afterward.
 
 You can assign the engine.echo property to True or False any time after
 creating the engine.
 
 Is there something that would trigger this to be recognized?
 
 In trying to use this to see the sql from a key piece of code it seems if I 
 have to do the engine.echo=True well in advance of when I want it to start; 
 and similarly I need to wait well after I want it to stop before I set it to 
 False. Otherwise I miss stuff.
 
 Thanks,
 Michael
 
 -- 
 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.



Re: [sqlalchemy] Empty a record

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 5:17 PM, Michael Hipp wrote:

 On 9/22/2010 11:21 AM, Michael Hipp wrote:
 
  new = Car()
  new.id_ = old.id_
  new = sess.merge(new)
  new.auction = old.auction # do this *after* merge
  sess.commit()
 
 This seems to work and  ...
 
 Bah. I spoke too soon - it just doesn't throw an exception.

that absolutely does what you tell it (guess thats not what you want).  Make 
sure Car's init is:

def __init__(self, lane=None, make='', auction=None):
self.lane = lane
self.make = make
if auction is not None:
self.auction = auction

then:

new = Car()
new.id_ = old.id_
new.lane = old.lane
new = sess.merge(new)
new.auction = old.auction
sess.commit()

SQL:

UPDATE cars SET make=? WHERE cars.id_ = ?
('', 1)


 But without explicitly setting every field to its default value, the session 
 thinks nothing has changed and the UPDATE leaves most of the fields untouched.
 
 Anyway, it appears I need a new approach to empty/blank a record. Options I 
 can think of are:

Here's the problem.  The term a blank record is meaningless.   You have to 
spell that out explicitly, on every class that has a concept of blank.   
Class A might consider fields x, y, z but not q, p, r to be part of blank, 
class B has some totally different idea.  Whether or not database fields have a 
default configured at the database level or table metadata level is also an 
artificial constraint...sure flip through table.c and look at default 
/server_default if you want that, but I've never written an app that had rules 
even that simplistic.

Trying to make other tools guess this for you seems to be taking up days of 
your time - whereas a simple def set_myself_blank(self) method OTOH would take 
30 seconds.


-- 
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] Empty a record

2010-09-22 Thread Michael Hipp

On 9/22/2010 5:24 PM, Michael Bayer wrote:

Here's the problem.  The term a blank record is meaningless.


Well, no, it's not. It's exactly what I get when I do new=Item() and commit(). 
It's very well defined, precise, and repeatable.



Trying to make other tools guess this for you seems to be taking up days of 
your time - whereas a simple def set_myself_blank(self) method OTOH would take 
30 seconds.


I've been writing that 30 second method for 2 days now. So evidently it takes 
longer than that :-)


Problem is that model has about 75 columns in it. Each Column() has a 
default='foo' parameter. And they are all unique to some extent.


So I can *replicate* that information that is already there in a dict somewhere 
that will have 75 lines in it and then maintain it in sync with the official 
version. That is a severe violation of DRY and it will inevitably lead to bugs 
and possibly data corruption.


Avoiding such seems a worthy goal.

I apologize, truly, that I have greatly overused your assistance on this. Thank 
you.


I have formulated a couple of hackish approaches that will probably work. Guess 
I'm stuck with them. :-)


Michael


--
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] Empty a record

2010-09-22 Thread Michael Bayer

On Sep 22, 2010, at 6:44 PM, Michael Hipp wrote:

 On 9/22/2010 5:24 PM, Michael Bayer wrote:
 Here's the problem.  The term a blank record is meaningless.
 
 Well, no, it's not. It's exactly what I get when I do new=Item() and 
 commit(). It's very well defined, precise, and repeatable.
 
 Trying to make other tools guess this for you seems to be taking up days of 
 your time - whereas a simple def set_myself_blank(self) method OTOH would 
 take 30 seconds.
 
 I've been writing that 30 second method for 2 days now. So evidently it takes 
 longer than that :-)
 
 Problem is that model has about 75 columns in it. Each Column() has a 
 default='foo' parameter. And they are all unique to some extent.
 
 So I can *replicate* that information that is already there in a dict 
 somewhere that will have 75 lines in it and then maintain it in sync with the 
 official version. That is a severe violation of DRY and it will inevitably 
 lead to bugs and possibly data corruption.
 
 Avoiding such seems a worthy goal.
 
 I apologize, truly, that I have greatly overused your assistance on this. 
 Thank you.
 
 I have formulated a couple of hackish approaches that will probably work. 
 Guess I'm stuck with them. :-)

I guess, even though you've never stated this very clearly, that a blank 
record means, you'd like the default value for all columns reset to the 
default ?   What if the default for a certain column is the current 
timestamp ?   How are you going to recreate that ?Or somehting set by a 
sequence or other stored procedure where the original value is missing ?   You 
probably don't have this issue but the idea of a blank record is still 
something somewhat specific to your situation.

Anyway as I said, read through the columns on table.c and use 
default/server_default. 

-- 
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: declarative - automatically add a primary key if the table doesn't have one

2010-09-22 Thread Yap Sok Ann


On Sep 22, 11:37 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 On Sep 22, 2010, at 4:30 AM, Yap Sok Ann wrote:



  This is related to topic need 0.6_beta2-compat declarative meta
 http://groups.google.com/group/sqlalchemy/browse_thread/thread/ae7cb9...

  Prior to version 0.6, I use the following code to automatically add a
  primary key if the table doesn't have one defined:

  from sqlalchemy.ext.declarative import declarative_base,
  DeclarativeMeta
  from sqlalchemy.schema import Column
  from sqlalchemy.types import Integer

  class Meta(DeclarativeMeta):
     def __init__(cls, classname, bases, dict_):
         for attr in dict_.itervalues():
             if isinstance(attr, Column) and attr.primary_key:
                 break
         else:
             dict_['id'] = Column(Integer, primary_key=True)
         return super(Meta, cls).__init__(classname, bases, dict_)

  Base = declarative_base(metaclass=Meta)

  Of course, that doesn't work anymore in 0.6. The suggestion from the
  aforementioned threads is to replace:

  dict_['id'] = Column(Integer, primary_key=True)

  with

  cls.id = Column(Integer, primary_key=True)

  Unfortunately, that alone doesn't work in this case. The problem is
  that the Base class itself will be the first one to go through the
  Meta.__init__() method, so the whole thing essentially becomes:

  Base.id = Column(Integer, primary_key=True)

  For it to work, I have to wrap the code in an if-block, i.e.

  class Meta(DeclarativeMeta):
     def __init__(cls, classname, bases, dict_):
         if classname != 'Base':
             for attr in dict_.itervalues():
                 if isinstance(attr, Column) and attr.primary_key:
                     break
             else:
                 cls.id = Column(Integer, primary_key=True)
         return super(Meta, cls).__init__(classname, bases, dict_)

  which looks rather ugly. Is there a cleaner way to achieve this?

 I didn't think metaclasses were supposed to be pretty ?    Checking that 
 you're not the base is pretty standard metaclass stuff.      If the 
 hardcoded name is the issue, you can look in bases:

         if object not in bases:

 or something more generic:

         for k in cls.__mro__[1:]:
             if isinstance(k, Meta):
                 # you're a Base subclass

Good point. I shall stick with the name checking solution then. Thank
you for your help.

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