On Mar 5, 2012, at 6:52 AM, Martijn Moeling wrote:

> I think I've got it working correctly.
> 
> 
> in my mixin I now do:
> 
>     @declared_attr
>     def id(self):
>         return ExtColumn('JSid',Unicode(255), default = None) 
> 
> so the id property is actually stored in the DB Column 'JSid'
> Since my introspection looks at the python class, it takes the name from the 
> class definition and put's 'id' in the json.
> 
> the only change is 'JSid' in the definition and no extra overhead is added.
> 
> This is nice since whilst solving this I found out that I have a few more of 
> these (i.e. Name and name)
> Since I use PostgreSQL I got away with this….


yeah I'm surprised you didn't know about the "attribute = 
Column("someothername", ) calling form ?     I point it out in several places 
in the docs, it has its own section: 
http://docs.sqlalchemy.org/en/latest/orm/mapper_config.html#naming-columns-distinctly-from-attribute-names
  and additionally 
http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative.html#defining-attributes
 .

Glad you got it working but also I will be looking into removing that lower() 
logic by default in 0.8 since it is usually wasteful.



> 
> Martijn
> 
> On Mar 5, 2012, at 11:55 , Martijn Moeling wrote:
> 
>> Michael,
>> 
>> Thank you for confirming my worries and adding reason to it.
>> 
>> I'm not sure if you remember al my questions in the past but with my project 
>> I'm constantly hitting the "impossible", although its fun, it can be 
>> frustrating sometimes.
>> 
>> What I'm doing is something bigger than just an application, I'm building an 
>> web based operating system, with Desktop in a browser and with a development 
>> system for applications.
>> 
>> It is based on Open Source products and build from absolute scratch, there 
>> is much more to it but as I signed  a non disclosure agreement with my self, 
>> I must stop here.
>> 
>> Since I Love Python and absolutely hate Javascript, HTML, CSS, I Have put a 
>> lot of effort in doing away with those and replace them with Python, 
>> Basically what I have is an IDE to develop web appellations which in itself 
>> is a web application. Within that you can write Python which is "Compiled" 
>> into all the parts needed by a browser.
>> It resembles something which is very close to Visual Basic 6.0 if you 
>> remember that one from a developer point of view.
>> 
>> Since I use the Id field for SA in the usual fashion, I struggle where I 
>> reflect Javascript objects with an "id" field.
>> Everything is generated with Introspection, I subclassed the SA Column to 
>> add properties to the colums. These are non functioning in "run" mode but 
>> are used when compiling to javascript. (the _constuctor returns the real 
>> Column, not the extended one).
>> 
>> the id column is coming from Python classes generated from the sources of 
>> ExtJs, the Id column is tightly bound to communication between browser and 
>> back-end (Since its the recordId).
>> 
>> at the end the Id column will be/is hidden from the developer, but I have 
>> tons and tons of code relying on Id.
>> Within the IDE a user would and should be able to instance an object with an 
>> "id" doing so in the creation is no problem since python differs between id 
>> and Id (and Id is never set by code)
>> 
>> so :
>> 
>> id   = ExtendedSAColumn(Unicode(25), default = ….)
>> 
>> will end up ad {xtype : 'textfield' , id : 'the id' ……}
>> 
>> For "compile time" I have no Issues with overhead
>> 
>> I can rename id to JS_id (or something) but I need to be able to do 
>> Someclass.id = 'the id'
>> 
>> and print Someclass.id (or use the value in some other way)
>> 
>> Since an Application and its components are reflected in the database, 
>> almost all classes which are compiled into javascript will have an id 
>> column. adding a @declared_attr to my mixin en a setter function and map id 
>> to JSid adds an id column to everything and that is not what I want (and 
>> messes with my introspection routines to reflect SA Database object classes)
>> 
>> I must find a way where the id field can be used in the IDE without adding 
>> any special code there, it should be transparent to users of my system.
>> 
>> Thing is, on some objects (maybe most, at least the ones which have to do 
>> with stores and models) I Introspect a Class and not an instance of that 
>> Class. While during "runtime" these python objects are used to query the 
>> database and converted to json to fit into the generated stores and models 
>> (as defined by Extjs). and during runtime all "overhead" is just not there, 
>> so translating JSid into id will be needed on each record, if it has an id 
>> property or not.
>> 
>> Is there a way to use declarative and map the id property to a different 
>> name?
>> 
>> 
>> like:
>> 
>> id           = Column(integer, name='JSid'……)
>> 
>> I have something similair to this:
>> I've left out the filtering of SA Colum arguments as I did with the 
>> processing of NON SA column arguments to __init__
>> 
>> class ExtColum(Column):
>> 
>> def __init__(self, type, *arg ,**kwarg):
>>      #filter out the SA Column properties into "filteredoptions" and:
>>      Column.__init__(self, type_, *arg,**filteredoptions)
>> 
>> def _constructor(self, name, type_ *a, **kw):
>>      column= Column(type,*a, **kw)
>>      column.name = name
>>      return column
>> 
>> 
>> in the _constructor I can mess with the name:
>> 
>> def _constructor(self,name, type_ *a,**kw):
>>      column= Column(type,*a, **kw)
>>      if name == "JSid":
>>              column.name = "id"
>>      else:
>>              column.name = name
>> 
>> I think this would fix runtime, as _constructor is called on record load 
>> but how to set the Column name in the __init__
>> 
>> My introspection routines would "see" the "id" column as an ExtColumn but 
>> would store it's value in JSid and not mess with the functionality of SA and 
>> or the database as "jsid" would NOT interfere with Id.
>> 
>> Solving it this way, the overhead is only on ExtColumn based Columns which 
>> saves a lot. Again this would be unusual use of SA for as far as I can see.
>> 
>> reading the docs for the Column object:
>> The name of this column as represented in the database. This argument may be 
>> the first positional argument, or specified via keyword.
>> 
>> Names which contain no upper case characters will be treated as case 
>> insensitive names, and will not be quoted unless they are a reserved word. 
>> Names with any number of upper case characters will be quoted and sent 
>> exactly. Note that this behavior applies even for databases which 
>> standardize upper case names as case insensitive such as Oracle.
>> 
>> The name field may be omitted at construction time and applied later, at any 
>> time before the Column is associated with a Table. This is to support 
>> convenient usage within the declarative extension.
>> 
>> 
>> the last paragraph is the most interesting. testing however makes me unsure 
>> where to put the name. and even more interesting, how to test for the name 
>> in the __init__ ?
>> 
>> for some reason I do not seem to get no reference to name, even after 
>> calling Column.__init__, self.name == None, Am I thinking in the wrong 
>> direction?
>> 
>> 
>> Martijn
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>>  
>> 
>>  
>> 
>> 
>> 
>> On Mar 5, 2012, at 00:06 , Michael Bayer wrote:
>> 
>>> 
>>> On Mar 4, 2012, at 2:18 PM, Martijn Moeling wrote:
>>> 
>>>> sqlalchemy.exc.DataError: (DataError) invalid input syntax for integer: 
>>>> "Blablabla"
>>>> LINE 3: WHERE ide_applicationcontroller."Application" = E'Blablabla...
>>>>                                                         ^
>>>>  'SELECT ide_controller."Id" AS "ide_controller_Id", ide_controller."Name" 
>>>> AS "ide_controller_Name", ide_controller."onLaunch" AS 
>>>> "ide_controller_onLaunch", ide_controller.id AS ide_controller_id \nFROM 
>>>> ide_controller, ide_applicationcontroller \nWHERE 
>>>> ide_applicationcontroller."Application" = %(param_1)s AND 
>>>> ide_applicationcontroller."Controller" = ide_controller."Id"' {'param_1': 
>>>> u'Blablabla'}
>>> 
>>> 
>>>> 
>>>> 
>>>> I do not understand where the "E" is coming from, I've check and checked 
>>>> and never reference to "id" anywhere by mistake
>>> 
>>> the "E" is part of how psycopg2/libpq renders bound parameters before 
>>> passing off to the backend, and is normal.
>>> 
>>> 
>>>> 
>>>> I can not freely choose my columnnames
>>> 
>>> OK well I can confirm the use case is not supported at all on SQLAlchemy - 
>>> SQLA is case insensitive in how it deals with result set column names.  
>>> It's been that way since the beginning and nobody has ever asked for it to 
>>> be changed, much less even noticed it, most likely.     Had I been making 
>>> this decision today, I would not have chosen the lower() option, as it adds 
>>> performance overhead in any case and is for the vast majority of cases 
>>> completely unnecessary.    However, I don't recall if I was coming up 
>>> against DBAPIs that were not giving me the correct casing within 
>>> cursor.description, and I'm not sure if all DBAPIs handle this correctly, 
>>> so there is some risk to changing the behavior.
>>> 
>>> So I'd point out that this use case you have here is exceedingly unusual.  
>>> Many databases don't support it, not even SQLite, which won't let me create 
>>> such a table, even if I quote both names:
>>> 
>>>     duplicate column name: Id u'\nCREATE TABLE a (\n\t"id" INTEGER NOT 
>>> NULL, \n\t"Id" INTEGER, \n\tPRIMARY KEY ("id")\n)\n\n' ()
>>> 
>>> nor will the current release of MySQL:
>>> 
>>>     (1060, "Duplicate column name 'Id'") '\nCREATE TABLE a (\n\t`id` 
>>> INTEGER NOT NULL AUTO_INCREMENT, \n\t`Id` INTEGER, \n\tPRIMARY KEY (`id`), 
>>> \n\tUNIQUE (`Id`)\n)\n\n' ()
>>> 
>>> So generally, mixing overlapping names based on case within relational 
>>> databases is a really bad idea, and is just asking for trouble at every 
>>> stage.  
>>> 
>>> 
>>>> and do not really want to run code for every parameter just to see if 
>>>> there is an id field and put the value in whatever other storage name, 
>>>> that will add unwanted load to my system.
>>> 
>>> So if your system is truly "generic" and you can't anticipate what existing 
>>> names are present, I'd point out that right off, your approach will not 
>>> work for SQLite or MySQL, which will not allow such a naming convention in 
>>> any case.
>>> 
>>> The logic we're talking about here would take place at configuration time 
>>> in any case, and would be a completely minuscule check that runs just once 
>>> per class at import time, so there's no "load" issue.    Also, what if you 
>>> were given a class that actually had the lowercase name "id" on it already? 
>>>  If you have no control over column names,  don't you need to check for 
>>> that name already existing?  Or are you publishing a restriction that this 
>>> name is "reserved", and in which case why not say that all casing 
>>> conventions of "id" are reserved as well ?
>>> 
>>> 
>>>> Is this a bug? or do I hit a Feature of SA where it does not matter if id 
>>>> or Id is used and somewhere a .lower() takes care of that. Can I switch it 
>>>> off if so?
>>> 
>>> The model for the statement compiler and result proxy works on a case 
>>> insensitive model right now as far as how columns are located in result 
>>> sets, I can't even get a plain row back using such a casing convention.
>>> 
>>> Ticket #2423 (http://www.sqlalchemy.org/trac/ticket/2423) illustrates a 
>>> patch that would allow the behavior to be configurable.   As anticipated, 
>>> it adds 7% method call overhead to key performance tests, when the "case 
>>> insensitive" behavior is turned on as it doubles the function call overhead 
>>> for each lower().   Which leads me to want to release it in 0.8 with the 
>>> default behavior reversed, thereby avoiding the double-function call for 
>>> the vast majority of cases that aren't attempting to refer to columns in a 
>>> case-insensitive manner.   But I'd have to do a deep sweep across all the 
>>> DBAPIs I can find, because if any of them are lowercasing on their end, 
>>> then the change will be incompatible - those DBAPIs might want to signal 
>>> that the flag turns back on.
>>> 
>>> 
>>> 
>>> -- 
>>> 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.
>> 
>> 
>> -- 
>> 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.
> 
> 
> -- 
> 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.

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

Reply via email to