Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

I think I've seen this ORM somewhere before...

Changeset 297

Show
Ignore:
Timestamp:
09/01/06 20:35:19
Author:
dowski
Message:

Implemented dejavu.month() and dejavu.day() for all SMs that can support it. Except firebird. Didn't touch firebird.

Tried implementing "Perfect Date" functionality for SQLite and hit a wall. See comments in storage/storesqlite.py.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/__init__.py

    r296 r297  
    109109        return None 
    110110 
     111def day(value): 
     112    """The day attribute of a date.""" 
     113    if isinstance(value, (_datetime.date, _datetime.datetime)): 
     114        return value.day 
     115    else: 
     116        return None 
     117 
    111118def now(): 
    112119    """Late-bound datetime.datetime.now(). Taint this when early binding.""" 
  • trunk/storage/geniusql.py

    r296 r297  
    797797        return "MONTH(" + x + ")" 
    798798     
     799    def dejavu_day(self, x): 
     800        return "DAY(" + x + ")" 
     801     
    799802    def func__builtin___len(self, x): 
    800803        return "LENGTH(" + x + ")" 
  • trunk/storage/storeado.py

    r296 r297  
    294294    def dejavu_today(self): 
    295295        return "DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)" 
     296     
     297    def dejavu_year(self, x): 
     298        return "DATEPART(year, " + x + ")" 
     299     
     300    def dejavu_month(self, x): 
     301        return "DATEPART(month, " + x + ")" 
     302     
     303    def dejavu_day(self, x): 
     304        return "DATEPART(day, " + x + ")" 
    296305     
    297306    def func__builtin___len(self, x): 
     
    813822    def dejavu_year(self, x): 
    814823        return "Year(" + x + ")" 
    815  
     824     
     825    def dejavu_month(self, x): 
     826        return "Month(" + x + ")" 
     827 
     828    def dejavu_day(self, x): 
     829        return "Day(" + x + ")" 
    816830 
    817831class TypeAdapter_MSAccess(db.TypeAdapter): 
  • trunk/storage/storepypgsql.py

    r296 r297  
    107107    def dejavu_month(self, x): 
    108108        return "date_part('month', " + x + ")" 
    109  
     109     
     110    def dejavu_day(self, x): 
     111        return "date_part('day', " + x + ")" 
    110112 
    111113 
  • trunk/storage/storesqlite.py

    r296 r297  
     1import datetime 
    12import os 
    23import time 
     
    910# This will import the "old API for SQLite 3.x", using e.g. pysqlite 1.1.7 
    1011import _sqlite 
     12 
    1113_version = storage.Version(_sqlite.sqlite_version()) 
    1214 
     
    2224_rename_table_support = (_version >= storage.Version([3, 1, 0])) 
    2325_autoincrement_support = (_version >= storage.Version([3, 1, 0])) 
    24  
     26_cast_support = (_version >= storage.Version([3, 2, 3])) 
    2527 
    2628class AdapterToSQLite(db.AdapterToSQL): 
     
    3335    bool_true = "1" 
    3436    bool_false = "0" 
     37     
     38    # If you are using type adapters that support a "standard" 
     39    # date/datetime format for SQLite, set the following flag to True 
     40    using_perfect_dates = False 
    3541     
    3642    def coerce_bool_to_any(self, value): 
     
    5258class SQLiteDecompiler(db.SQLDecompiler): 
    5359     
     60    def visit_COMPARE_OP(self, lo, hi): 
     61        if self.adapter.using_perfect_dates: 
     62            op2, op1 = self.stack.pop(), self.stack.pop() 
     63            #@@NOTE: date/datetime comparision 
     64            # This code seems to work fine, but see the NOTE in visit_LOAD_ATTR 
     65            # for the problem... 
     66             
     67            # SQLite can do meaningful date/datetime comparisions with 
     68            # Julian dates.  It has a function to convert a string date 
     69            # to a Julian date.  We make use of it here. 
     70            if (isinstance(op1, db.ConstWrapper) and 
     71                isinstance(op1.basevalue, (datetime.date, datetime.datetime))): 
     72                op1 = "julianday(" + op1 + ")" 
     73             
     74            elif (isinstance(op2, db.ConstWrapper) and 
     75                  isinstance(op2.basevalue, (datetime.date, datetime.datetime))): 
     76                op2 = "julianday(" + op2 + ")" 
     77                 
     78            # Put the operands back on the stack so that the standard 
     79            # visit_COMPARE_OP can have its way with them. 
     80            self.stack.append(op1) 
     81            self.stack.append(op2) 
     82             
     83        db.SQLDecompiler.visit_COMPARE_OP(self, lo, hi) 
     84     
     85    def visit_LOAD_ATTR(self, lo, hi): 
     86        name = self.co_names[lo + (hi << 8)] 
     87        tos = self.stack.pop() 
     88        if isinstance(tos, tuple): 
     89            # The name in question refers to a DB column. 
     90            tablename, table = tos 
     91            col = table.columns[name] 
     92            if col.imperfect_type: 
     93                atom = db.cannot_represent 
     94                self.imperfect = True 
     95            # @@NOTE: date/datetime comparision 
     96            # I hit a wall here.  With the lack of a definitive date/datetime 
     97            # coltype in SQLite, and with the Python type of a column being 
     98            # determined by a different adapter, I have no way of determining 
     99            # if I should wrap a [table].[column] reference in the julianday() 
     100            # function :-(  I would like to do something like ... 
     101            # elif col.pytype in (datetime.date, datetime.datetime): 
     102            #     atom = "julianday(%s.%s)" % (tablename, col.qname) 
     103            else: 
     104                atom = '%s.%s' % (tablename, col.qname) 
     105        else: 
     106            # 'tos.name' will reference an attribute of the tos object. 
     107            # Stick the tos and name in a tuple for later processing. 
     108            atom = (tos, name) 
     109        self.stack.append(atom) 
     110     
    54111    def attr_startswith(self, tos, arg): 
    55112        if _escape_support: 
     
    127184     
    128185    def dejavu_now(self): 
    129         self.imperfect = True 
    130         return db.cannot_represent 
     186        if self.adapter.using_perfect_dates and _cast_support: 
     187            return "julianday('now')" 
     188        else: 
     189            self.imperfect = True 
     190            return db.cannot_represent 
    131191     
    132192    dejavu_today = dejavu_now 
    133193     
    134194    def dejavu_year(self, x): 
    135         self.imperfect = True 
    136         return db.cannot_represent 
    137  
     195        if self.adapter.using_perfect_dates and _cast_support: 
     196            return "CAST(strftime('%Y', " + x + ") AS NUMERIC)" 
     197        else: 
     198            self.imperfect = True 
     199            return db.cannot_represent 
     200     
    138201    def dejavu_month(self, x): 
    139         self.imperfect = True 
    140         return db.cannot_represent 
    141  
     202        if self.adapter.using_perfect_dates and _cast_support: 
     203            return "CAST(strftime('%m', " + x + ") AS NUMERIC)" 
     204        else: 
     205            self.imperfect = True 
     206            return db.cannot_represent 
     207     
     208    def dejavu_day(self, x): 
     209        if self.adapter.using_perfect_dates and _cast_support: 
     210            return "CAST(strftime('%d', " + x + ") AS NUMERIC)" 
     211        else: 
     212            self.imperfect = True 
     213            return db.cannot_represent 
    142214 
    143215class TypeAdapterSQLite(db.TypeAdapter): 
     
    358430     
    359431    columnsetclass = SQLiteColumnSet 
     432     
     433    def isrelatedtype(self, pytype1, pytype2): 
     434        if (self.using_perfect_dates and 
     435            issubclass(pytype1, (datetime.date, datetime.time, datetime.datetime)) and 
     436            issubclass(pytype2, self.python_type(self.typeadapter.coerce(None, pytype1)))): 
     437            return True 
     438        return db.Database.isrelatedtype(self, pytype1, pytype2) 
    360439     
    361440    def _get_tables(self, conn=None): 
     
    557636        allOptions['mode'] = int(allOptions.pop('Mode', '0755'), 8) 
    558637        db.StorageManagerDB.__init__(self, arena, allOptions) 
     638        pd = str(allOptions.get('Perfect Dates', 'False')).lower() == "true" 
     639        self.databaseclass.using_perfect_dates = pd 
     640        self.databaseclass.adaptertosql.using_perfect_dates = pd 
    559641     
    560642    def version(self): 
  • trunk/test/test_storesqlite.py

    r296 r297  
    1919         
    2020        print 
    21         print "Testing SQLite ':memory:' database...
    22         opts['Database'] = ':memory:' 
     21        print "Testing SQLite with 'Perfect Dates'
     22        opts['Perfect Dates'] = True 
    2323        reload(zoo_fixture) 
    2424        zoo_fixture.init() 
    2525        zoo_fixture.run(SM_class, opts) 
     26        opts['Perfect Dates'] = False 
     27         
     28##        print 
     29##        print "Testing SQLite ':memory:' database..." 
     30##        opts['Database'] = ':memory:' 
     31##        reload(zoo_fixture) 
     32##        zoo_fixture.init() 
     33##        zoo_fixture.run(SM_class, opts) 
    2634         
    2735        print 
  • trunk/test/zoo_fixture.py

    r296 r297  
    421421        self.assertEqual(matches(lambda x: 'i' in x.Species), 7) 
    422422         
    423         # Test now(), today(), year(), month() 
     423        # Test now(), today(), year(), month(), day() 
    424424        self.assertEqual(matches(lambda x: x.Founded != None 
    425425                                 and x.Founded < dejavu.today(), Zoo), 3) 
     
    427427        self.assertEqual(matches(lambda x: dejavu.year(x.LastEscape) == 2004), 1) 
    428428        self.assertEqual(matches(lambda x: dejavu.month(x.LastEscape) == 12), 1) 
     429        self.assertEqual(matches(lambda x: dejavu.day(x.LastEscape) == 21), 1) 
    429430 
    430431