I have seen it in the docs and that is where the solution came from.
When not interested in a property I tend to remember it is there but not read
into it, which is normal I guess..
I was looking at some commented out code in that bit and saw I had tried
name='JSid' but since "name" was used in Extending SA.Column for my use.
Interested in why I tried that I looked into the docs to find out the "First
Property" option. This saved my ass!! as name='something' would have worked
normally but not in this particular case….
On Mar 5, 2012, at 15:45 , Michael Bayer wrote:
>
> 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.
--
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.