Contact: fumanchu@aminus.org

Log in as guest/geniusql to create tickets

Changeset 73

Show
Ignore:
Timestamp:
04/12/07 00:05:17
Author:
fumanchu
Message:

Fixed some precision conversion issues from base 2 to base 10. Also added a 'signed' canonical hint.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/geniusql/adapters.py

    r72 r73  
    4343maxint_bytes = 1 
    4444while True: 
     45    # Signed values have half the max of unsigned (hence the "-1"). 
    4546    if sys.maxint <= 2 ** ((maxint_bytes * 8) - 1): 
    4647        break 
  • trunk/geniusql/dbtypes.py

    r72 r73  
    33 
    44import datetime 
     5import math 
    56 
    67from geniusql import adapters, errors, typerefs 
     
    324325    """Base class for SQL 92 REAL types.""" 
    325326    default_pytype = float 
     327    # By "precision" here, we mean the number of binary digits 
     328    # which can be safely round-tripped to the DB and back. 
     329    # Even though almost every DB will use 32 bits to represent this 
     330    # number (1 sign bit, 8 exponent bits, and 24 significand bits), 
     331    # we're only interested in the significand bits; therefore, the 
     332    # max() for this type should be (2 ** 24) - 1. 
     333    # See http://babbage.cs.qc.edu/IEEE-754/Decimal.html 
    326334    _precision = max_precision = 24 
    327335    default_adapters = {float: adapters.float_to_SQL92REAL()} 
     
    480488        that merely looks up synonyms, database types MUST be 
    481489        canonicalized for all Column and SQLExpression objects. 
     490         
     491        Note that the caller is responsible to strip out any metadata from 
     492        the supplied type name; for example, "NUMERIC(18, 2)" should 
     493        (usually) be reduced to "NUMERIC" before calling this function. 
     494        However, this is not mandatory; some providers may need to use 
     495        such metadata to select the most appropriate type. 
    482496        """ 
    483497        for typeset in self.known_types.itervalues(): 
     
    493507        hints: if provided, this should be a dict of property attributes 
    494508            which can be used to distinguish between similar database types. 
    495             Canonical keys include 'bytes', 'precision', and 'scale'. 
     509            Canonical keys include 'bytes', 'precision', 'scale', 
     510            and 'signed'. 
    496511        """ 
    497512        xform = "dbtype_for_" + getCoerceName(pytype) 
     
    507522    def dbtype_for_float(self, hints): 
    508523        """Return a DatabaseType for floats of the given binary precision.""" 
    509         # Note that 'precision' is binary digits, not decimal. 
     524        # Note that 'precision' is binary digits, not decimal digits or bytes. 
     525        # FOr example, most DOUBLE PRECISION types are implemented as 
     526        # 64 bits ~= 53 binary precision ~= 14 decimal precision 
    510527        precision = int(hints.get('precision', adapters.maxfloat_digits)) 
    511528        if precision == 0: 
     
    618635     
    619636    def dbtype_for_long(self, hints): 
     637        # Assume most people want signed numbers. 
     638        signed = hints.get('signed', True) 
     639         
    620640        if 'bytes' in hints: 
    621641            bytes = int(hints['bytes']) 
    622         else: 
    623             bytes = self.numeric_max_precision() / 2 
     642            maxprec = int(math.ceil(math.log(2 ** (bytes * 8), 10))) 
     643        else: 
     644            maxprec = self.numeric_max_precision() 
     645            bytes = int(math.ceil(math.log(10 ** maxprec, 2) / 8)) 
    624646         
    625647        for dbtype in self.known_types['int']: 
    626             if bytes <= dbtype.max_bytes
     648            if bytes <= dbtype.max_bytes and signed == dbtype.signed
    627649                return dbtype(bytes=bytes) 
    628         return self.decimal_type(precision=bytes * 2, scale=0) 
     650         
     651        return self.decimal_type(precision=maxprec, scale=0) 
    629652     
    630653    def dbtype_for_int(self, hints): 
     654        # Assume most people want signed numbers; maxint_bytes assumes it. 
     655        signed = hints.get('signed', True) 
    631656        bytes = int(hints.get('bytes', adapters.maxint_bytes)) 
     657         
    632658        for dbtype in self.known_types['int']: 
    633             if bytes <= dbtype.max_bytes
     659            if bytes <= dbtype.max_bytes and signed == dbtype.signed
    634660                return dbtype(bytes=bytes) 
    635         return self.decimal_type(precision=bytes * 2, scale=0) 
    636  
     661         
     662        maxprec = int(math.ceil(math.log(2 ** (bytes * 8), 10))) 
     663        return self.decimal_type(precision=maxprec, scale=0) 
     664