From: Billy G. A. <bal...@us...> - 2005-03-01 21:07:12
|
Update of /cvsroot/pypgsql/pypgsql/pyPgSQL In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25157/pyPgSQL Modified Files: PgSQL.py Log Message: 01MAR2005 bga Implemented most outstanding bug fixes and patches. Index: PgSQL.py =================================================================== RCS file: /cvsroot/pypgsql/pypgsql/pyPgSQL/PgSQL.py,v retrieving revision 1.44 retrieving revision 1.45 diff -C2 -d -r1.44 -r1.45 *** PgSQL.py 27 Feb 2005 18:40:04 -0000 1.44 --- PgSQL.py 1 Mar 2005 21:06:44 -0000 1.45 *************** *** 30,33 **** --- 30,38 ---- # Date Ini Description | # --------- --- ------------------------------------------------------- | + # 27FEB2005 bga - Bug fix release to catch up with the outstanding bug | + # reports. | + # 27FEB2005 gh - Converted all checks for Unicode types to isinstance | + # checks. Fixes bugs #1055180, #1051520, #1016026, | + # #1016010. | # 31JUL2004 bga - Fixed mis-spelling of __comm to __conn. | # [Bug #1001242] | *************** *** 460,463 **** --- 465,474 ---- TimestampFromTicks = DateTime.TimestampFromTicks + #--------------------------------------------------+ + # The RelativeDateTime type for PgInterval support | + #--------------------------------------------------+ + + RelativeDateTime = DateTime.RelativeDateTime + #-----------------------------------------------+ # The DateTimeDelta type for PgInterval support | *************** *** 472,476 **** DateTimeType = DateTime.DateTimeType DateTimeDeltaType = DateTime.DateTimeDeltaType - DateTimeDelta = DateTime.DateTimeDelta #-----------------------------------------------------------------------+ --- 483,486 ---- *************** *** 583,586 **** --- 593,602 ---- """Type cache -- used to cache postgreSQL data type information.""" + _time_units = ( + ( 'days', 'day'), + ( 'months', 'month', 'mon', 'mons' ), + ( 'years', 'year'), + ) + def __init__(self, conn): if noWeakRef: *************** *** 611,614 **** --- 627,651 ---- ydh = ydh[2:] + # Convert any months using 30 days per month, which is PostgreSQL's + # assumption about the number of days in a months IF it doesn't + # know the end or start date of the interval. If PG DOES know either + # date it will use the correct length of the month, eg 28-31 days. + # However, at this stage we have no way of telling which one it + # was. If you want to work with accurate intervals (eg. post-processing + # them) you need to use date1-date2 syntax rather than age(date1, date2) + # in your queries. + # + # This is per discussion on pgsql-general: + # http://www.spinics.net/lists/pgsql/msg09668.html + # Google for: + # >>>"interval output format" available that removes ambiguity<<< + # + # Note: Should a notice be provided to the user that post-processing + # year/month intervals is unsafe practice ? + if len(ydh) > 1: + if ydh[1].lower().startswith('mon'): + result += parser('%s days' % ((int(ydh[0]) * 30),)) + ydh = ydh[2:] + # Converts any days and adds it to the years (as an interval) if len(ydh) > 1: *************** *** 623,626 **** --- 660,694 ---- return result + def interval2RelativeDateTime(self, s): + """Parses PostgreSQL INTERVALs. + The expected format is [[[-]YY years] [-]DD days] [-]HH:MM:SS.ss""" + + tokens = s.split() + quantity = None + result = RelativeDateTime() + for token in tokens: + # looking for quantity + if token.isdigit() or token[0] == '-' and token[1:].isdigit(): + quantity = int(token) + continue + # looking for unit + elif token.isalpha() and not quantity is None: + unitAttr = None + for unit in self._time_units: + if token in unit: + unitAttr = unit[0] + if unitAttr and not quantity is None: + setattr(result, unitAttr, quantity) + quantity = None + continue + # looking for time + elif token.find(':') != -1: + hms = [ int(value) for value in token.split(':') ] + result.hour = hms[0] + result.minute= hms[1] + if len(hms) == 3: + result.second = hms[2] + return result + def parseArray(self, s): """Parse a PostgreSQL array strings representation. *************** *** 829,839 **** return PgMoney(value).value elif _ftv == DATETIME: ! if type(value) in [DateTimeType, DateTimeDeltaType]: return value else: if _ftv == PG_INTERVAL: ! return self.interval2DateTimeDelta(value) else: ! return DateTime.ISO.ParseAny(value) elif _ftv == BINARY: if isinstance(value, PgBytea) or type(value) is PgLargeObjectType: --- 897,914 ---- return PgMoney(value).value elif _ftv == DATETIME: ! if type(value) is DateTimeType: ! if value in ('infinity', '+infinity', '-infinity'): ! fake_infinity = '9999-12-13 23:59:59' # fake infinity ! if value[0] == '-': ! value = '-' + fake_infinity ! else: ! value = fake_infinity return value else: if _ftv == PG_INTERVAL: ! return self.interval2RelativeDateTime(value) else: ! return DateTime.Parser.DateTimeFromString(value) ! #return DateTime.ISO.ParseAny(value) elif _ftv == BINARY: if isinstance(value, PgBytea) or type(value) is PgLargeObjectType: *************** *** 888,892 **** lst[_i] = PgInt2(lst[_i]) elif _ftv == DATETIME: ! lst[_i] = DateTime.ISO.ParseAny(lst[_i]) elif _ftv == PG_MONEY: if lst[_i][0] == '(': --- 963,978 ---- lst[_i] = PgInt2(lst[_i]) elif _ftv == DATETIME: ! if _fvt != PG_INTERVAL: ! if lst[_i] in ('infinity', '+infinity', '-infinity'): ! fake_infinity = '9999-12-13 23:59:59' # fake infinity ! if lst[_i][0] == '-': ! lst[_i] = '-' + fake_infinity ! else: ! lst[_i] = fake_infinity ! else: ! lst[_i] = DateTime.Parser.DateTimeFromString(lst[_i]) ! #lst[_i] = DateTime.ISO.ParseAny(lst[_i]) ! else: ! lst[i] = self.interval2RelativeDateTime(lst{_i]) elif _ftv == PG_MONEY: if lst[_i][0] == '(': *************** *** 1455,1459 **** # and scale. It can also make a copy of a PgNumeric. self.__v = value.__v ! if scale: self.__s = scale _ds = scale - value.__s --- 1541,1545 ---- # and scale. It can also make a copy of a PgNumeric. self.__v = value.__v ! if scale is not None: self.__s = scale _ds = scale - value.__s *************** *** 1669,1673 **** _c = self.__coerce__(other) if _c is None: ! return None self, other = _c if self.__s < other.__s: --- 1755,1759 ---- _c = self.__coerce__(other) if _c is None: ! return 1 self, other = _c if self.__s < other.__s: *************** *** 1698,1706 **** def _quote(self, forArray=0): ! if self.__v != None: if forArray: return '"%s"' % self.__fmtNumeric() else: ! return "'%s'" % self.__fmtNumeric() return 'NULL' --- 1784,1792 ---- def _quote(self, forArray=0): ! if self.__v is not None: if forArray: return '"%s"' % self.__fmtNumeric() else: ! return self.__fmtNumeric() return 'NULL' *************** *** 1853,1861 **** def _quote(self, forArray=0): ! if self.value: if forArray: return '"%s"' % str(self.value) else: ! return "'%s'" % str(self.value) return 'NULL' --- 1939,1947 ---- def _quote(self, forArray=0): ! if self.value is not None: if forArray: return '"%s"' % str(self.value) else: ! return str(self.value) return 'NULL' *************** *** 2191,2195 **** # ary using _quote. | # dateTimeDelta2Interval() -- converts a DateTimeDelta type into | ! # a string PostgreSQL accepts as a interval. | #-----------------------------------------------------------------------+ --- 2277,2283 ---- # ary using _quote. | # dateTimeDelta2Interval() -- converts a DateTimeDelta type into | ! # a string PostgreSQL accepts as an interval. | ! # relativeDateTime2Interval() -- converts a RelativeDateTime into | ! # a string PostgreSQL accepts as an interval. | #-----------------------------------------------------------------------+ *************** *** 2266,2269 **** --- 2354,2359 ---- elif type(_i) is DateTime.DateTimeDeltaType: _j = '%s"%s",' % (_j, dateTimeDelta2Interval(_i)) + elif isinstance(value, RelativeDateTime): + _j = '%s"%s",' % (_j, relativeDateTime2Interval(_i)) elif type(_i) is PgInt2Type or isinstance(_i, PgInt8Type): _j = '%s%s,' % (_j, str(_i)) *************** *** 2295,2298 **** --- 2385,2390 ---- elif type(value) is DateTimeDeltaType: return "'%s'" % dateTimeDelta2Interval(value) + elif isinstance(value, RelativeDateTime): + return "'%s'" % relativeDateTime2Interval(value) elif isinstance(value, StringType): return PgQuoteString(value) *************** *** 2358,2361 **** --- 2450,2469 ---- raise TypeException, "DateTimeDelta2Interval requires a DataTimeDelta." + + def relativeDateTime2Interval(interval): + """ + relativeDateTime2Interval - Converts a RelativeDateTime to an interval string\n + The output format is YYYY years M mons DD days HH:MM:SS\n + """ + + if type(interval) is RelativeDateTime: + return "%s years %s mons %s days %02i:%02i:%02i" % ( + interval.years, interval.months, interval.days, + interval.hours, interval.minutes, interval.seconds + ) + else: + raise TypeException, \ + "relativeDateTime2Interval requires a RelativeDateTime" + #-----------------------------------------------------------------------+ # Name: Connection | *************** *** 2849,2853 **** break elif count > 0: ! for _i in range(count): _j = self.__fetchOneRow() if _j is not None: --- 2957,2961 ---- break elif count > 0: ! for _i in xrange(count): _j = self.__fetchOneRow() if _j is not None: |