Thread: [SQLObject] Auto-generating Joins
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: Christopher S. <csi...@gm...> - 2008-02-07 17:06:25
|
I've got some object classes related like so: class ObjectState(SQLObject): parent = ForeignKey('Object') date = DateCol() attribute = StringCol() class Object(SQLObject): states = MultipleJoin('ObjectState', joinColumn='parent_id') When I subclass them, I don't want to have to keep repeating the ObjectState.parent and Object.states attribute definitions. I'd like to autogenerate the string arguments passed to ForeignKey and MultipleJoin, based on the name of the class. Ideally it would look something like this: class ObjectState(SQLObject): parent = ForeignKey(class.__name__[:-5]) date = DateCol() attribute = StringCol() class Object(SQLObject): states = MultipleJoin(class.__name__+'State', joinColumn='parent_id') Which leads to some questions: 1) How do I access the name of the class in the class definition? 2) If I can set these parent/states attributes like this, will it inherit correctly for subclasses? I'd appreciate help from somebody who's set up something like this before, or else suggestions on other means of accomplishing this goal. TIA, cs |
From: Oleg B. <ph...@ph...> - 2008-02-07 17:21:49
|
On Thu, Feb 07, 2008 at 11:06:05AM -0600, Christopher Singley wrote: > class Object(SQLObject): > states = MultipleJoin(class.__name__+'State', joinColumn='parent_id') > > Which leads to some questions: > 1) How do I access the name of the class in the class definition? No way. This is Python's limitation. You can access the class in its metaclass, but please be careful - SQLObject already uses metaclasses. > 2) If I can set these parent/states attributes like this, will it inherit > correctly for subclasses? No. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 17:36:20
|
On Thursday 07 February 2008 11:21:46 Oleg Broytmann wrote: > No. Maybe my design is a bad solution for the problem. I want to define a SQLObject that is static, so that its id can be used as a foreign key, but I want to allow its attributes to change dynamically, with the entire history persisted. That's why I wrote this: ======= class ObjectState(SQLObject): parent = ForeignKey('Object') date = DateCol() attribute = StringCol() class Object(SQLObject): states = MultipleJoin('ObjectState', joinColumn='parent_id') ======= Surely this must be a common goal; is there a better approach? TIA, cs |
From: Oleg B. <ph...@ph...> - 2008-02-07 17:58:51
|
On Thu, Feb 07, 2008 at 11:36:15AM -0600, Christopher Singley wrote: > class ObjectState(SQLObject): > parent = ForeignKey('Object') > date = DateCol() > attribute = StringCol() > > class Object(SQLObject): > states = MultipleJoin('ObjectState', joinColumn='parent_id') So an Object instance has a lot of states, well... > SQLObject that is static, so that its id can be used as a foreign key, but I > want to allow its attributes to change dynamically What do you mean by "changing dynamically"? > with the entire history > persisted. http://sqlobject.org/Versioning.html Is it what you want? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 19:14:23
|
On Thursday 07 February 2008 11:58:34 Oleg Broytmann wrote: > What do you mean by "changing dynamically"? I mean "dynamical system" where the state of the system is a function of time. I need a function which accepts a time variable as an input, and returns a state. Consider exchange-traded securities (e.g. stocks). An important attribute of a stock is its price. Stock trading prices are a time series of discrete points. Yahoo Finance, among others, persists series of prices and allows users to look them up by time. That's the kind of thing I'm talking about: |
From: Christopher S. <csi...@gm...> - 2008-02-07 19:18:34
|
On Thursday 07 February 2008 13:14:16 I wrote: > On Thursday 07 February 2008 11:58:34 Oleg Broytmann wrote: > > What do you mean by "changing dynamically"? > > I mean "dynamical system" where the state of the system is a function of > time. I need a function which accepts a time variable as an input, and > returns a state. > > Consider exchange-traded securities (e.g. stocks). An important attribute > of a stock is its price. Stock trading prices are a time series of > discrete points. Yahoo Finance, among others, persists series of prices > and allows users to look them up by time. That's the kind of thing I'm > talking about: So then: class SecurityState(SQLObject): parent = ForeignKey('Security') date = DateCol() price = DecimalCol(size=10, precision=4) class Security(SQLObject): states = MultipleJoin('SecurityState', joinColumn='parent_id') Why define a separate class for security? So that Security.id can be used as a foreign key in other tables. For example: class SecurityTransaction(SQLObject): time = DateTimeCol() price = DecimalCol(size=10, precision=4) security = ForeignKey('Security') Is there a better way of representing data like this in SQL/SQLObject? TIA, cs |
From: Oleg B. <ph...@ph...> - 2008-02-07 19:34:22
|
On Thu, Feb 07, 2008 at 01:18:33PM -0600, Christopher Singley wrote: > > I mean "dynamical system" where the state of the system is a function of > > time. I need a function which accepts a time variable as an input, and > > returns a state. > > > > Consider exchange-traded securities (e.g. stocks). An important attribute > > of a stock is its price. Stock trading prices are a time series of > > discrete points. Yahoo Finance, among others, persists series of prices > > and allows users to look them up by time. That's the kind of thing I'm > > talking about: > > So then: > class SecurityState(SQLObject): > parent = ForeignKey('Security') > date = DateCol() > price = DecimalCol(size=10, precision=4) > > class Security(SQLObject): > states = MultipleJoin('SecurityState', joinColumn='parent_id') > > Why define a separate class for security? So that Security.id can be used as > a foreign key in other tables. For example: > > class SecurityTransaction(SQLObject): > time = DateTimeCol() > price = DecimalCol(size=10, precision=4) > security = ForeignKey('Security') > > Is there a better way of representing data like this in SQL/SQLObject? I don't think so, and I think you scheme is very good for the task. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 20:04:56
Attachments:
sqlobjectextensions.py
|
On Thursday 07 February 2008 13:34:16 Oleg Broytmann wrote: > On Thu, Feb 07, 2008 at 01:18:33PM -0600, Christopher Singley wrote: > > > I mean "dynamical system" where the state of the system is a function > > > of time. I need a function which accepts a time variable as an input, > > > and returns a state. > > > > > > Consider exchange-traded securities (e.g. stocks). An important > > > attribute of a stock is its price. Stock trading prices are a time > > > series of discrete points. Yahoo Finance, among others, persists > > > series of prices and allows users to look them up by time. That's the > > > kind of thing I'm talking about: > > > > So then: > > class SecurityState(SQLObject): > > parent = ForeignKey('Security') > > date = DateCol() > > price = DecimalCol(size=10, precision=4) > > > > class Security(SQLObject): > > states = MultipleJoin('SecurityState', joinColumn='parent_id') > > > > Why define a separate class for security? So that Security.id can be > > used as a foreign key in other tables. For example: > > > > class SecurityTransaction(SQLObject): > > time = DateTimeCol() > > price = DecimalCol(size=10, precision=4) > > security = ForeignKey('Security') > > > > Is there a better way of representing data like this in SQL/SQLObject? > > I don't think so, and I think you scheme is very good for the task. > > Oleg. Well, as I wrote in my original email on this thread, I am trying to solve this problem in a generic way, then subclass it. It is verbose & error-prone to keep writing the ForeignKey/MultipleJoin, when there's an easy rule to predict what is needed ahead of time. Any ideas for a more elegant solution? If anybody's interested, and it will help to specify the problem, I've attached the actual code I'm writing (warning - probably still contains errors). I'm talking about the DynamicState and DynamicSQLObject classes, which are themselves subclasses of simpler classes I wrote to implement user-friendly lookup & merge functionality. These are very general classes helping me in the way I use SQLObject to make things. If they are of any use to anybody else, you are welcome to use them, as long as you don't try to hold me responsible for any consequences. Feedback is of course appreciated. Sorry if the comments in the code are extremely verbose, but that's the way I do things since I'm not an experienced programmer. TIA, cs |
From: Oleg B. <ph...@ph...> - 2008-02-07 20:32:16
|
I very much hope you understand that .count() does a separate query which could be very expensive, and you call .count() two times! if selectResults.count(): try: assert selectResults.count()==1 Either cache the result of the first .count() or better avoid it at all and use list(selectResults). Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 21:03:09
|
On Thursday 07 February 2008 14:32:09 Oleg Broytmann wrote: > I very much hope you understand that .count() does a separate query which > could be very expensive, and you call .count() two times! Thank you very much for the suggestion; it's easy to change to len(list(selectResults)). Any ideas for how to improve the class definition syntax for my DynamicState/ DynamicSQLObject? To see the problem, below are some subclasses showing how they're used. I'm trying to represent the US federal employers' tax. These rules change every year, so they are well represented by DynamicState/ DynamicSQLObject. As you can see, it's pretty unfortunate to keep cutting&pasting all those parent/stateClass/states attributes. If anybody's got any ideas for how to make this syntax tighter, I'd be very much obliged. TIA, cs === class TaxRule(sqlobjectextensions.DynamicState): parent = sqlobject.ForeignKey('Tax', notNone=True) signature = ('date',) dontCreateTable = True class Tax(sqlobjectextensions.DynamicSQLObject): stateClass = TaxRule states = sqlobject.MultipleJoin('TaxRule', joinColumn='parent_id') dontCreateTable = True class FlatRateTaxRule(TaxRule): parent = sqlobject.ForeignKey('Tax', notNone=True) rate = DecimalCol(size=6, precision=5, notNone=True) dontCreateTable = True class FlatRateTax(sqlobjectextensions.DynamicSQLObject): stateClass = FlatRateTaxRule states = sqlobject.MultipleJoin('FlatRateTaxRule', joinColumn='parent_id') dontCreateTable = True class MedicareRule(FlatRateTaxRule): parent = sqlobject.ForeignKey('Medicare', notNone=True) class Medicare(FlatRateTax): stateClass = MedicareRule states = sqlobject.MultipleJoin('MedicareRule', joinColumn='parent_id') class FlatRateTaxWithCeilingRule(FlatRateTaxRule): ceiling = CurrencyCol(notNone=True) ceilingPeriod = ForeignKey('Periodicity', notNone=True) dontCreateTable = True class FlatRateTaxWithCeiling(FlatRateTax): stateClass = FlatRateTaxWithCeilingRule states = sqlobject.MultipleJoin('FlatRateTaxWithCeilingRule', joinColumn='parent_id') dontCreateTable = True class SocialSecurityRule(FlatRateTaxWithCeilingRule): parent = sqlobject.ForeignKey('SocialSecurity', notNone=True) class SocialSecurity(FlatRateTax): stateClass = SocialSecurityRule states = sqlobject.MultipleJoin('SocialSecurityRule', joinColumn='parent_id') class FutaRule(FlatRateTaxWithCeilingRule): parent = sqlobject.ForeignKey('Futa', notNone=True) class Futa(FlatRateTaxWithCeiling): stateClass = FutaRule states = sqlobject.MultipleJoin('FutaRule', joinColumn='parent_id') class EmployeeIncomeTaxRule(TaxRule): parent = sqlobject.ForeignKey('EmployeeIncomeTax', notNone=True) married = BoolCol(notNone=True) payrollPeriod = ForeignKey('Periodicity', notNone=True) minWage = CurrencyCol(notNone=True) maxWage = CurrencyCol(notNone=True) baseWithholding = CurrencyCol(notNone=True) excessRate = DecimalCol(size=5, precision=4, notNone=True) signature = ('married', 'payrollPeriod', 'date') dontCreateTable = True class EmployeeIncomeTax(Tax): stateClass = EmployeeIncomeTaxRule states = sqlobject.MultipleJoin('EmployeeIncomeTaxRule', joinColumn='parent_id') dontCreateTable = True |
From: Oleg B. <ph...@ph...> - 2008-02-07 21:26:20
|
On Thu, Feb 07, 2008 at 03:03:05PM -0600, Christopher Singley wrote: > On Thursday 07 February 2008 14:32:09 Oleg Broytmann wrote: > > I very much hope you understand that .count() does a separate query which > > could be very expensive, and you call .count() two times! > > Thank you very much for the suggestion; it's easy to change to > len(list(selectResults)). Again, you better cache the list as you need the item from the list: result = list(selectResults) if result: if len(result) == 1: return result[0] else: ... else: ... > Any ideas for how to improve the class definition syntax for my DynamicState/ > DynamicSQLObject? To see the problem, below are some subclasses showing how > they're used. I'm trying to represent the US federal employers' tax. These > rules change every year, so they are well represented by DynamicState/ > DynamicSQLObject. > > As you can see, it's pretty unfortunate to keep cutting&pasting all those > parent/stateClass/states attributes. If anybody's got any ideas for how to > make this syntax tighter, I'd be very much obliged. These pairs could be generated in a loop, but I doubt it'd be any simpler because then you will need to manipulate SQLObject's class registry which is usually handled automagically. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 21:51:50
|
On Thursday 07 February 2008 15:26:17 Oleg Broytmann wrote: > Again, you better cache the list as you need the item from the list: > > result = list(selectResults) > if result: > if len(result) == 1: > return result[0] > else: > ... > else: > ... Yes, I did cache the list; my revised code is this: === selectResults = list(selectResults) if selectResults: try: assert len(selectResults)==1 except AssertionError: ... object = selectResults[0] else: object = None return object === > These pairs could be generated in a loop, but I doubt it'd be any > simpler because then you will need to manipulate SQLObject's class registry > which is usually handled automagically. All right then, I guess that's a reasonable effort to make it "as simple as possible, but not simpler" (to quote Einstein). Is there any sort of repository anywhere for SQLObject subclasses and extensions, like the Python Cheese Shop? I feel like I am reinventing the wheel with some of these classes. Anyway, thanks for your help. SQLObject is a pleasure to work with. cs |
From: Oleg B. <ph...@ph...> - 2008-02-07 21:58:38
|
On Thu, Feb 07, 2008 at 03:51:46PM -0600, Christopher Singley wrote: > All right then, I guess that's a reasonable effort to make it "as simple > as possible, but not simpler" (to quote Einstein). I think so, too. > Is there any sort of repository anywhere for SQLObject subclasses and > extensions, like the Python Cheese Shop? Alas! There were two wiki sites but both are dead now. The lack of resources on the admin site, and probably the lack of interest on the user side. > Anyway, thanks for your help. SQLObject is a pleasure to work with. Thank you! Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-07 22:38:06
|
On Thursday 07 February 2008 15:58:37 Oleg Broytmann wrote: > Alas! There were two wiki sites but both are dead now. The lack of > resources on the admin site, and probably the lack of interest on the user > side. Strange... isn't there supposed to be some renaissance of interest in ORM tools happening now? (Web 2.0 etc. etc.) Anyway, if you're not tired of answering questions yet... what about SQLObject's mapping of DecimalCol to sqlite? I don't really understand the sqlite docs: """A column with NUMERIC affinity may contain values using all five storage classes. When text data is inserted into a NUMERIC column, an attempt is made to convert it to an integer or real number before it is stored. If the conversion is successful, then the value is stored using the INTEGER or REAL storage class. If the conversion cannot be performed the value is stored using the TEXT storage class. No attempt is made to convert NULL or blob values.""" Does that mean my fixed-point data will be converted to floating point?? No, no, no! Have you had any experience with sqlite's storage fidelity for decimal #s? I will test this, but it's worth asking first. TIA, cs |
From: Oleg B. <ph...@ph...> - 2008-02-08 08:53:45
|
On Thu, Feb 07, 2008 at 04:38:04PM -0600, Christopher Singley wrote: > On Thursday 07 February 2008 15:58:37 Oleg Broytmann wrote: > > Alas! There were two wiki sites but both are dead now. The lack of > > resources on the admin site, and probably the lack of interest on the user > > side. > > Strange... isn't there supposed to be some renaissance of interest in ORM > tools happening now? (Web 2.0 etc. etc.) Probably, but SQLObject is far from being the only ORM in the Python world, or even the most popular, though it's one of the most popular. > Anyway, if you're not tired of answering questions yet... what about > SQLObject's mapping of DecimalCol to sqlite? SQLObject has its own methods of converting/coercing data to/from Python from/to DB. Of course, SQLObject can only operate on the data returned by DB API driver - PySQLite in your case, so if PySQLite returns a float, SQLObject converts the float to a Decimal (via str(), yes). > Have you had any experience with sqlite's storage fidelity for decimal #s? I have, as I have a few Decimal columns in the database of one of our company's commercial programs - we count money (dollars and cents). Until now none of our customers has problems, though I doubt one has tried to sum up all those cents and fractions. If you find a problem - please publish more details. In case of PySQLite there is a way to map data to/from strings for any data; currently SQLObject uses this feature to map strings to/from unicode, and map date/time strings; it would be possible to add a mapping for Decimals. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-08 17:06:48
|
On Friday 08 February 2008 02:53:45 Oleg Broytmann wrote: > I have, as I have a few Decimal columns in the database of one of our > company's commercial programs - we count money (dollars and cents). Until > now none of our customers has problems, though I doubt one has tried to > sum up all those cents and fractions. If I can find the time, I'd like to implement a double-entry journal/ledger accounting system in SQLObject. Accounting reconciliation involves strict equalities; even slightly inaccurate recording of cents & fractions causes a lot of unnecessary extra work. That's why I'm afraid of floating point. I am too dumb to understand sqlite's data storage model, but quick consultation of Google yields up this conversation from just last weekend: http://www.mail-archive.com/sql...@sq.../msg31198.html """ The case I'm dealing with that is not working like I want is the case of NUMERIC column type. In SQLite, this column type gets an affinity of REAL. If I put in a value to the column as a string literal, say '123.23', it's stored as a REAL even though I specified it as a string in quotes. [...] I want to avoid the use of REAL types in this case because they can lead to rounding errors, which is the whole purpose of the NUMERIC type to begin with, in my understanding. """ Needless to say, this frightens me. But rather than dropping the ideal of serverless installs of desktop apps, I am interested if there's a better way. > If you find a problem - please publish more details. In case of PySQLite > there is a way to map data to/from strings for any data; currently > SQLObject uses this feature to map strings to/from unicode, and map > date/time strings; it would be possible to add a mapping for Decimals. That sounds like a better way! Strings should be a fine way to store fixed-point numbers of finite length. Are there any considerations that might make this a bad idea? cs |
From: Oleg B. <ph...@ph...> - 2008-02-08 17:26:00
|
On Fri, Feb 08, 2008 at 11:06:40AM -0600, Christopher Singley wrote: > On Friday 08 February 2008 02:53:45 Oleg Broytmann wrote: > > If you find a problem - please publish more details. In case of PySQLite > > there is a way to map data to/from strings for any data; currently > > SQLObject uses this feature to map strings to/from unicode, and map > > date/time strings; it would be possible to add a mapping for Decimals. > > That sounds like a better way! Strings should be a fine way to store > fixed-point numbers of finite length. Are there any considerations that > might make this a bad idea? If you are going to use (or allow to use) the DB in external non-python tools you have to document the mapping, and even the documents could not help in case of standard tools that don't know anything about the mapping. The mapping is a function of PySQLite2, not SQLite itself: http://initd.org/pub/software/pysqlite/doc/usage-guide.html#sqlite-and-python-types Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-08 18:42:13
|
On Friday 08 February 2008 11:25:57 Oleg Broytmann wrote: > If you are going to use (or allow to use) the DB in external non-python > tools you have to document the mapping, and even the documents could not > help in case of standard tools that don't know anything about the mapping. > The mapping is a function of PySQLite2, not SQLite itself: > http://initd.org/pub/software/pysqlite/doc/usage-guide.html#sqlite-and-pyth >on-types I guess the mapping Decimal <-> str ought to be pretty easy, since it's supported by Python's decimal module. Are we talking about modifying sqlobject.sqlite.sqliteconnection.__init__() to define adapter/converter function and register them with pysqlite? Wouldn't that just be about 4 lines of code? Or what are the relevant data structures? You'll have to pardon me. I don't mind doing work, but looking at the SQLObject source code makes my head spin a little bit. cs |
From: Oleg B. <ph...@ph...> - 2008-02-08 19:03:46
|
On Fri, Feb 08, 2008 at 12:41:54PM -0600, Christopher Singley wrote: > I guess the mapping Decimal <-> str ought to be pretty easy, since it's > supported by Python's decimal module. I don't remember Decimal can do conversion to string and back from string preserving precision. Are you talking about converting to floating-point string? str(Decimal("1.1")) => '1.1'? I don't know if the conversion preserves all digits. But if it does - that's the way to go, of course. > Are we talking about modifying sqlobject.sqlite.sqliteconnection.__init__() to > define adapter/converter function and register them with pysqlite? Yes. > Wouldn't > that just be about 4 lines of code? Plus tests, plus at least a line in News.txt, plus thinking if it breaks something for those who now use floats with DecimalCol. > You'll have to pardon me. I don't mind doing work, but looking at the > SQLObject source code makes my head spin a little bit. Is it really that bad? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-08 19:57:10
|
On Friday 08 February 2008 13:03:42 Oleg Broytmann wrote: > I don't remember Decimal can do conversion to string and back from > string preserving precision. Are you talking about converting to > floating-point string? str(Decimal("1.1")) => '1.1'? I don't know if the > conversion preserves all digits. But if it does - that's the way to go, of > course. http://www.python.org/dev/peps/pep-0327/#documentation PEP 327 says that str(Decimal()) implements the to-scientific-string function required by IBM's Decimal Arithmetic Specification. http://www2.hursley.ibm.com/decimal/daconvs.html#reftostr Unless the developers grossly misimplemented the spec, then the coefficient will contain all significant digits. An example of this usage is included in the Python Library Reference for the module. http://docs.python.org/lib/decimal-tutorial.html > > Wouldn't > > that just be about 4 lines of code? > > Plus tests, plus at least a line in News.txt, plus thinking if it breaks > something for those who now use floats with DecimalCol. I wouldn't know how to write a test. As for the last, I'm trying to think of how improved accuracy would screw up somebody's code. It could be a problem if SQLObject no longer works with their existing sqlite databases, but I think that ought to be solveable. It could be a problem if they want to access their sqlite databases with other tools outside of SQLObject. > > You'll have to pardon me. I don't mind doing work, but looking at the > > SQLObject source code makes my head spin a little bit. > > Is it really that bad? I'm just a novice programmer, and you guys do some reasonably sophisticated stuff in there. I can't even figure out whether SODecimalCol objects actually have attributes representing the values persisted in the database, and if so what they're called. cs |
From: Oleg B. <ph...@ph...> - 2008-02-08 20:05:17
|
On Fri, Feb 08, 2008 at 01:57:03PM -0600, Christopher Singley wrote: > On Friday 08 February 2008 13:03:42 Oleg Broytmann wrote: > > I don't remember Decimal can do conversion to string and back from > > string preserving precision. Are you talking about converting to > > floating-point string? str(Decimal("1.1")) => '1.1'? I don't know if the > > conversion preserves all digits. But if it does - that's the way to go, of > > course. > > http://www.python.org/dev/peps/pep-0327/#documentation > PEP 327 says that str(Decimal()) implements the to-scientific-string function > required by IBM's Decimal Arithmetic Specification. > http://www2.hursley.ibm.com/decimal/daconvs.html#reftostr > > Unless the developers grossly misimplemented the spec, then the coefficient > will contain all significant digits. > > An example of this usage is included in the Python Library Reference for the > module. > http://docs.python.org/lib/decimal-tutorial.html Yes, after some thinking and experimenting I believe it saves all digits. After all, it is called Decimal for purpose. > I wouldn't know how to write a test. I am saving the thread in my mailbox and will do the dirty work later. I think the implementation will be even simpler than registering adapter/converter. SQLObject could do all the work itself. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-12 23:37:33
|
Following up on this issue - here is a test. === from decimal import Decimal from sqlobject import * sqlhub.processConnection = connectionForURI('sqlite:///path/to/decimaltest.db') class Test(SQLObject): number = DecimalCol(size=8, precision=4) Test.createTable(ifNotExists=True) foo = Test(number=Decimal('23')) foo.sqlmeta.expired=True print type(foo.number) === When I run this test, it indicates that sqlobject can return DecimalCol values as nondecimals. cs |
From: Oleg B. <ph...@ph...> - 2008-02-13 11:12:18
|
On Tue, Feb 12, 2008 at 05:37:26PM -0600, Christopher Singley wrote: > foo = Test(number=Decimal('23')) > print type(foo.number) Good catch. Can you believe I am going to fix the entire problem with such small and simple patch as Index: col.py =================================================================== --- col.py (revision 3248) +++ col.py (working copy) @@ -1330,6 +1330,9 @@ return [DecimalValidator()] + \ super(SODecimalCol, self).createValidators() + def _sqliteType(self): + return "TEXT" + class DecimalCol(Col): baseClass = SODecimalCol ? The idea is to change type affinity in SQLite from NUMERIC (int/float) to TEXT to forbid SQLite to convert Decimal strings to floats. On the other hand that could bring problems with SQL manipulations such as ORDER BY... Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Christopher S. <csi...@gm...> - 2008-02-13 23:11:29
|
On Wednesday 13 February 2008 05:12:13 Oleg Broytmann wrote: > On the other hand that could bring problems with SQL manipulations such > as ORDER BY... Not sure how important that functionality is, but couldn't problems be fixed by prepending zero padding? Perhaps the str.rjust() function could be used. I believe every DecimalCol explicitly declares a size, so the total width should be easy to calculate (i.e. size+1). cs |
From: Oleg B. <ph...@ph...> - 2008-02-13 23:24:50
|
On Wed, Feb 13, 2008 at 05:11:13PM -0600, Christopher Singley wrote: > I believe every DecimalCol explicitly declares a size, so the total width > should be easy to calculate (i.e. size+1). Couldn't we get an incorrect result trying to compare right-padding "009.11" and "2112.123456789"? I.e., could we rely solely on the size, not counting the number of digits in fraction? Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |