|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692 |
- """ Unit tests version 2.6.1.0 for adodbapi"""
- """
- adodbapi - A python DB API 2.0 interface to Microsoft ADO
-
- Copyright (C) 2002 Henrik Ekelund
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- Updates by Vernon Cole
- """
-
- import copy
- import datetime
- import decimal
- import random
- import string
- import sys
- import unittest
-
- try:
- import win32com.client
-
- win32 = True
- except ImportError:
- win32 = False
-
- # run the configuration module.
- import adodbapitestconfig as config # will set sys.path to find correct version of adodbapi
-
- # in our code below, all our switches are from config.whatever
- import tryconnection
-
- import adodbapi
- import adodbapi.apibase as api
-
- try:
- import adodbapi.ado_consts as ado_consts
- except ImportError: # we are doing a shortcut import as a module -- so
- try:
- import ado_consts
- except ImportError:
- from adodbapi import ado_consts
-
-
- def str2bytes(sval):
- return sval.encode("latin1")
-
-
- long = int
-
-
- def randomstring(length):
- return "".join([random.choice(string.ascii_letters) for n in range(32)])
-
-
- class CommonDBTests(unittest.TestCase):
- "Self contained super-simple tests in easy syntax, should work on everything between mySQL and Oracle"
-
- def setUp(self):
- self.engine = "unknown"
-
- def getEngine(self):
- return self.engine
-
- def getConnection(self):
- raise NotImplementedError # "This method must be overriden by a subclass"
-
- def getCursor(self):
- return self.getConnection().cursor()
-
- def testConnection(self):
- crsr = self.getCursor()
- assert crsr.__class__.__name__ == "Cursor"
-
- def testErrorHandlerInherits(self):
- if not self.remote:
- conn = self.getConnection()
- mycallable = lambda connection, cursor, errorclass, errorvalue: 1
- conn.errorhandler = mycallable
- crsr = conn.cursor()
- assert (
- crsr.errorhandler == mycallable
- ), "Error handler on crsr should be same as on connection"
-
- def testDefaultErrorHandlerConnection(self):
- if not self.remote:
- conn = self.getConnection()
- del conn.messages[:]
- try:
- conn.close()
- conn.commit() # Should not be able to use connection after it is closed
- except:
- assert len(conn.messages) == 1
- assert len(conn.messages[0]) == 2
- assert conn.messages[0][0] == api.ProgrammingError
-
- def testOwnErrorHandlerConnection(self):
- if self.remote: # ToDo: use "skip"
- return
- mycallable = (
- lambda connection, cursor, errorclass, errorvalue: 1
- ) # does not raise anything
- conn = self.getConnection()
- conn.errorhandler = mycallable
- conn.close()
- conn.commit() # Should not be able to use connection after it is closed
- assert len(conn.messages) == 0
-
- conn.errorhandler = None # This should bring back the standard error handler
- try:
- conn.close()
- conn.commit() # Should not be able to use connection after it is closed
- except:
- pass
- # The Standard errorhandler appends error to messages attribute
- assert (
- len(conn.messages) > 0
- ), "Setting errorhandler to none should bring back the standard error handler"
-
- def testDefaultErrorHandlerCursor(self):
- crsr = self.getConnection().cursor()
- if not self.remote:
- del crsr.messages[:]
- try:
- crsr.execute("SELECT abbtytddrf FROM dasdasd")
- except:
- assert len(crsr.messages) == 1
- assert len(crsr.messages[0]) == 2
- assert crsr.messages[0][0] == api.DatabaseError
-
- def testOwnErrorHandlerCursor(self):
- if self.remote: # ToDo: should be a "skip"
- return
- mycallable = (
- lambda connection, cursor, errorclass, errorvalue: 1
- ) # does not raise anything
- crsr = self.getConnection().cursor()
- crsr.errorhandler = mycallable
- crsr.execute("SELECT abbtytddrf FROM dasdasd")
- assert len(crsr.messages) == 0
-
- crsr.errorhandler = None # This should bring back the standard error handler
- try:
- crsr.execute("SELECT abbtytddrf FROM dasdasd")
- except:
- pass
- # The Standard errorhandler appends error to messages attribute
- assert (
- len(crsr.messages) > 0
- ), "Setting errorhandler to none should bring back the standard error handler"
-
- def testUserDefinedConversions(self):
- if self.remote: ## Todo: should be a "skip"
- return
- try:
- duplicatingConverter = lambda aStringField: aStringField * 2
- assert duplicatingConverter("gabba") == "gabbagabba"
-
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- # the variantConversions attribute should not exist on a normal connection object
- self.assertRaises(AttributeError, lambda x: conn.variantConversions[x], [2])
- if not self.remote:
- # create a variantConversions attribute on the connection
- conn.variantConversions = copy.copy(api.variantConversions)
- crsr = conn.cursor()
- tabdef = (
- "CREATE TABLE xx_%s (fldData VARCHAR(100) NOT NULL, fld2 VARCHAR(20))"
- % config.tmp
- )
- crsr.execute(tabdef)
- crsr.execute(
- "INSERT INTO xx_%s(fldData,fld2) VALUES('gabba','booga')"
- % config.tmp
- )
- crsr.execute(
- "INSERT INTO xx_%s(fldData,fld2) VALUES('hey','yo')" % config.tmp
- )
- # change converter for ALL adoStringTypes columns
- conn.variantConversions[api.adoStringTypes] = duplicatingConverter
- crsr.execute(
- "SELECT fldData,fld2 FROM xx_%s ORDER BY fldData" % config.tmp
- )
-
- rows = crsr.fetchall()
- row = rows[0]
- self.assertEqual(row[0], "gabbagabba")
- row = rows[1]
- self.assertEqual(row[0], "heyhey")
- self.assertEqual(row[1], "yoyo")
-
- upcaseConverter = lambda aStringField: aStringField.upper()
- assert upcaseConverter("upThis") == "UPTHIS"
-
- # now use a single column converter
- rows.converters[1] = upcaseConverter # convert second column
- self.assertEqual(row[0], "heyhey") # first will be unchanged
- self.assertEqual(row[1], "YO") # second will convert to upper case
-
- finally:
- try:
- del conn.variantConversions # Restore the default
- except:
- pass
- self.helpRollbackTblTemp()
-
- def testUserDefinedConversionForExactNumericTypes(self):
- # variantConversions is a dictionary of conversion functions
- # held internally in adodbapi.apibase
- #
- # !!! this test intentionally alters the value of what should be constant in the module
- # !!! no new code should use this example, to is only a test to see that the
- # !!! deprecated way of doing this still works. (use connection.variantConversions)
- #
- if not self.remote and sys.version_info < (3, 0): ### Py3 need different test
- oldconverter = adodbapi.variantConversions[
- ado_consts.adNumeric
- ] # keep old function to restore later
- # By default decimal and "numbers" are returned as decimals.
- # Instead, make numbers return as floats
- try:
- adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtFloat
- self.helpTestDataType(
- "decimal(18,2)", "NUMBER", 3.45, compareAlmostEqual=1
- )
- self.helpTestDataType(
- "numeric(18,2)", "NUMBER", 3.45, compareAlmostEqual=1
- )
- # now return strings
- adodbapi.variantConversions[ado_consts.adNumeric] = adodbapi.cvtString
- self.helpTestDataType("numeric(18,2)", "NUMBER", "3.45")
- # now a completly weird user defined convertion
- adodbapi.variantConversions[ado_consts.adNumeric] = (
- lambda x: "!!This function returns a funny unicode string %s!!" % x
- )
- self.helpTestDataType(
- "numeric(18,2)",
- "NUMBER",
- "3.45",
- allowedReturnValues=[
- "!!This function returns a funny unicode string 3.45!!"
- ],
- )
- finally:
- # now reset the converter to its original function
- adodbapi.variantConversions[
- ado_consts.adNumeric
- ] = oldconverter # Restore the original convertion function
-
- def helpTestDataType(
- self,
- sqlDataTypeString,
- DBAPIDataTypeString,
- pyData,
- pyDataInputAlternatives=None,
- compareAlmostEqual=None,
- allowedReturnValues=None,
- ):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- crsr = conn.cursor()
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldData """
- % config.tmp
- + sqlDataTypeString
- + ")\n"
- )
-
- crsr.execute(tabdef)
-
- # Test Null values mapped to None
- crsr.execute("INSERT INTO xx_%s (fldId) VALUES (1)" % config.tmp)
-
- crsr.execute("SELECT fldId,fldData FROM xx_%s" % config.tmp)
- rs = crsr.fetchone()
- self.assertEqual(rs[1], None) # Null should be mapped to None
- assert rs[0] == 1
-
- # Test description related
- descTuple = crsr.description[1]
- assert descTuple[0] in ["fldData", "flddata"], 'was "%s" expected "%s"' % (
- descTuple[0],
- "fldData",
- )
-
- if DBAPIDataTypeString == "STRING":
- assert descTuple[1] == api.STRING, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.STRING.values,
- )
- elif DBAPIDataTypeString == "NUMBER":
- assert descTuple[1] == api.NUMBER, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.NUMBER.values,
- )
- elif DBAPIDataTypeString == "BINARY":
- assert descTuple[1] == api.BINARY, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.BINARY.values,
- )
- elif DBAPIDataTypeString == "DATETIME":
- assert descTuple[1] == api.DATETIME, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.DATETIME.values,
- )
- elif DBAPIDataTypeString == "ROWID":
- assert descTuple[1] == api.ROWID, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.ROWID.values,
- )
- elif DBAPIDataTypeString == "UUID":
- assert descTuple[1] == api.OTHER, 'was "%s" expected "%s"' % (
- descTuple[1],
- api.OTHER.values,
- )
- else:
- raise NotImplementedError # "DBAPIDataTypeString not provided"
-
- # Test data binding
- inputs = [pyData]
- if pyDataInputAlternatives:
- inputs.extend(pyDataInputAlternatives)
- inputs = set(inputs) # removes redundant string==unicode tests
- fldId = 1
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_%s (fldId,fldData) VALUES (?,?)" % config.tmp,
- (fldId, inParam),
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldData FROM xx_%s WHERE ?=fldID" % config.tmp, [fldId]
- )
- rs = crsr.fetchone()
- if allowedReturnValues:
- allowedTypes = tuple([type(aRV) for aRV in allowedReturnValues])
- assert isinstance(
- rs[0], allowedTypes
- ), 'result type "%s" must be one of %s' % (type(rs[0]), allowedTypes)
- else:
- assert isinstance(
- rs[0], type(pyData)
- ), 'result type "%s" must be instance of %s' % (
- type(rs[0]),
- type(pyData),
- )
-
- if compareAlmostEqual and DBAPIDataTypeString == "DATETIME":
- iso1 = adodbapi.dateconverter.DateObjectToIsoFormatString(rs[0])
- iso2 = adodbapi.dateconverter.DateObjectToIsoFormatString(pyData)
- self.assertEqual(iso1, iso2)
- elif compareAlmostEqual:
- s = float(pyData)
- v = float(rs[0])
- assert (
- abs(v - s) / s < 0.00001
- ), "Values not almost equal recvd=%s, expected=%f" % (rs[0], s)
- else:
- if allowedReturnValues:
- ok = False
- self.assertTrue(
- rs[0] in allowedReturnValues,
- 'Value "%s" not in %s' % (repr(rs[0]), allowedReturnValues),
- )
- else:
- self.assertEqual(
- rs[0],
- pyData,
- 'Values are not equal recvd="%s", expected="%s"'
- % (rs[0], pyData),
- )
-
- def testDataTypeFloat(self):
- self.helpTestDataType("real", "NUMBER", 3.45, compareAlmostEqual=True)
- self.helpTestDataType("float", "NUMBER", 1.79e37, compareAlmostEqual=True)
-
- def testDataTypeDecmal(self):
- self.helpTestDataType(
- "decimal(18,2)",
- "NUMBER",
- 3.45,
- allowedReturnValues=["3.45", "3,45", decimal.Decimal("3.45")],
- )
- self.helpTestDataType(
- "numeric(18,2)",
- "NUMBER",
- 3.45,
- allowedReturnValues=["3.45", "3,45", decimal.Decimal("3.45")],
- )
- self.helpTestDataType(
- "decimal(20,2)",
- "NUMBER",
- 444444444444444444,
- allowedReturnValues=[
- "444444444444444444.00",
- "444444444444444444,00",
- decimal.Decimal("444444444444444444"),
- ],
- )
- if self.getEngine() == "MSSQL":
- self.helpTestDataType(
- "uniqueidentifier",
- "UUID",
- "{71A4F49E-39F3-42B1-A41E-48FF154996E6}",
- allowedReturnValues=["{71A4F49E-39F3-42B1-A41E-48FF154996E6}"],
- )
-
- def testDataTypeMoney(self): # v2.1 Cole -- use decimal for money
- if self.getEngine() == "MySQL":
- self.helpTestDataType(
- "DECIMAL(20,4)", "NUMBER", decimal.Decimal("-922337203685477.5808")
- )
- elif self.getEngine() == "PostgreSQL":
- self.helpTestDataType(
- "money",
- "NUMBER",
- decimal.Decimal("-922337203685477.5808"),
- compareAlmostEqual=True,
- allowedReturnValues=[
- -922337203685477.5808,
- decimal.Decimal("-922337203685477.5808"),
- ],
- )
- else:
- self.helpTestDataType("smallmoney", "NUMBER", decimal.Decimal("214748.02"))
- self.helpTestDataType(
- "money", "NUMBER", decimal.Decimal("-922337203685477.5808")
- )
-
- def testDataTypeInt(self):
- if self.getEngine() != "PostgreSQL":
- self.helpTestDataType("tinyint", "NUMBER", 115)
- self.helpTestDataType("smallint", "NUMBER", -32768)
- if self.getEngine() not in ["ACCESS", "PostgreSQL"]:
- self.helpTestDataType(
- "bit", "NUMBER", 1
- ) # Does not work correctly with access
- if self.getEngine() in ["MSSQL", "PostgreSQL"]:
- self.helpTestDataType(
- "bigint",
- "NUMBER",
- 3000000000,
- allowedReturnValues=[3000000000, int(3000000000)],
- )
- self.helpTestDataType("int", "NUMBER", 2147483647)
-
- def testDataTypeChar(self):
- for sqlDataType in ("char(6)", "nchar(6)"):
- self.helpTestDataType(
- sqlDataType,
- "STRING",
- "spam ",
- allowedReturnValues=["spam", "spam", "spam ", "spam "],
- )
-
- def testDataTypeVarChar(self):
- if self.getEngine() == "MySQL":
- stringKinds = ["varchar(10)", "text"]
- elif self.getEngine() == "PostgreSQL":
- stringKinds = ["varchar(10)", "text", "character varying"]
- else:
- stringKinds = [
- "varchar(10)",
- "nvarchar(10)",
- "text",
- "ntext",
- ] # ,"varchar(max)"]
-
- for sqlDataType in stringKinds:
- self.helpTestDataType(sqlDataType, "STRING", "spam", ["spam"])
-
- def testDataTypeDate(self):
- if self.getEngine() == "PostgreSQL":
- dt = "timestamp"
- else:
- dt = "datetime"
- self.helpTestDataType(
- dt, "DATETIME", adodbapi.Date(2002, 10, 28), compareAlmostEqual=True
- )
- if self.getEngine() not in ["MySQL", "PostgreSQL"]:
- self.helpTestDataType(
- "smalldatetime",
- "DATETIME",
- adodbapi.Date(2002, 10, 28),
- compareAlmostEqual=True,
- )
- if tag != "pythontime" and self.getEngine() not in [
- "MySQL",
- "PostgreSQL",
- ]: # fails when using pythonTime
- self.helpTestDataType(
- dt,
- "DATETIME",
- adodbapi.Timestamp(2002, 10, 28, 12, 15, 1),
- compareAlmostEqual=True,
- )
-
- def testDataTypeBinary(self):
- binfld = str2bytes("\x07\x00\xE2\x40*")
- arv = [binfld, adodbapi.Binary(binfld), bytes(binfld)]
- if self.getEngine() == "PostgreSQL":
- self.helpTestDataType(
- "bytea", "BINARY", adodbapi.Binary(binfld), allowedReturnValues=arv
- )
- else:
- self.helpTestDataType(
- "binary(5)", "BINARY", adodbapi.Binary(binfld), allowedReturnValues=arv
- )
- self.helpTestDataType(
- "varbinary(100)",
- "BINARY",
- adodbapi.Binary(binfld),
- allowedReturnValues=arv,
- )
- if self.getEngine() != "MySQL":
- self.helpTestDataType(
- "image", "BINARY", adodbapi.Binary(binfld), allowedReturnValues=arv
- )
-
- def helpRollbackTblTemp(self):
- self.helpForceDropOnTblTemp()
-
- def helpForceDropOnTblTemp(self):
- conn = self.getConnection()
- with conn.cursor() as crsr:
- try:
- crsr.execute("DROP TABLE xx_%s" % config.tmp)
- if not conn.autocommit:
- conn.commit()
- except:
- pass
-
- def helpCreateAndPopulateTableTemp(self, crsr):
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldData INTEGER
- )
- """
- % config.tmp
- )
- try: # EAFP
- crsr.execute(tabdef)
- except api.DatabaseError: # was not dropped before
- self.helpForceDropOnTblTemp() # so drop it now
- crsr.execute(tabdef)
- for i in range(9): # note: this poor SQL code, but a valid test
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES (%i)" % (config.tmp, i))
- # NOTE: building the test table without using parameter substitution
-
- def testFetchAll(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- rs = crsr.fetchall()
- assert len(rs) == 9
- # test slice of rows
- i = 3
- for row in rs[3:-2]: # should have rowid 3..6
- assert row[0] == i
- i += 1
- self.helpRollbackTblTemp()
-
- def testPreparedStatement(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.prepare("SELECT fldData FROM xx_%s" % config.tmp)
- crsr.execute(crsr.command) # remember the one that was prepared
- rs = crsr.fetchall()
- assert len(rs) == 9
- assert rs[2][0] == 2
- self.helpRollbackTblTemp()
-
- def testWrongPreparedStatement(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.prepare("SELECT * FROM nowhere")
- crsr.execute(
- "SELECT fldData FROM xx_%s" % config.tmp
- ) # should execute this one, not the prepared one
- rs = crsr.fetchall()
- assert len(rs) == 9
- assert rs[2][0] == 2
- self.helpRollbackTblTemp()
-
- def testIterator(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- for i, row in enumerate(
- crsr
- ): # using cursor as an iterator, rather than fetchxxx
- assert row[0] == i
- self.helpRollbackTblTemp()
-
- def testExecuteMany(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- seq_of_values = [(111,), (222,)]
- crsr.executemany(
- "INSERT INTO xx_%s (fldData) VALUES (?)" % config.tmp, seq_of_values
- )
- if crsr.rowcount == -1:
- print(
- self.getEngine()
- + " Provider does not support rowcount (on .executemany())"
- )
- else:
- self.assertEqual(crsr.rowcount, 2)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- rs = crsr.fetchall()
- assert len(rs) == 11
- self.helpRollbackTblTemp()
-
- def testRowCount(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- if crsr.rowcount == -1:
- # print("provider does not support rowcount on select")
- pass
- else:
- self.assertEqual(crsr.rowcount, 9)
- self.helpRollbackTblTemp()
-
- def testRowCountNoRecordset(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("DELETE FROM xx_%s WHERE fldData >= 5" % config.tmp)
- if crsr.rowcount == -1:
- print(self.getEngine() + " Provider does not support rowcount (on DELETE)")
- else:
- self.assertEqual(crsr.rowcount, 4)
- self.helpRollbackTblTemp()
-
- def testFetchMany(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- rs = crsr.fetchmany(3)
- assert len(rs) == 3
- rs = crsr.fetchmany(5)
- assert len(rs) == 5
- rs = crsr.fetchmany(5)
- assert len(rs) == 1 # Asked for five, but there is only one left
- self.helpRollbackTblTemp()
-
- def testFetchManyWithArraySize(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("SELECT fldData FROM xx_%s" % config.tmp)
- rs = crsr.fetchmany()
- assert len(rs) == 1 # arraysize Defaults to one
- crsr.arraysize = 4
- rs = crsr.fetchmany()
- assert len(rs) == 4
- rs = crsr.fetchmany()
- assert len(rs) == 4
- rs = crsr.fetchmany()
- assert len(rs) == 0
- self.helpRollbackTblTemp()
-
- def testErrorConnect(self):
- conn = self.getConnection()
- kw = {}
- if "proxy_host" in conn.kwargs:
- kw["proxy_host"] = conn.kwargs["proxy_host"]
- conn.close()
- self.assertRaises(api.DatabaseError, self.db, "not a valid connect string", kw)
-
- def testRowIterator(self):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- crsr = conn.cursor()
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldTwo integer,
- fldThree integer,
- fldFour integer)
- """
- % config.tmp
- )
- crsr.execute(tabdef)
-
- inputs = [(2, 3, 4), (102, 103, 104)]
- fldId = 1
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_%s (fldId,fldTwo,fldThree,fldFour) VALUES (?,?,?,?)"
- % config.tmp,
- (fldId, inParam[0], inParam[1], inParam[2]),
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldTwo,fldThree,fldFour FROM xx_%s WHERE ?=fldID" % config.tmp,
- [fldId],
- )
- rec = crsr.fetchone()
- # check that stepping through an emulated row works
- for j in range(len(inParam)):
- assert (
- rec[j] == inParam[j]
- ), 'returned value:"%s" != test value:"%s"' % (rec[j], inParam[j])
- # check that we can get a complete tuple from a row
- assert tuple(rec) == inParam, 'returned value:"%s" != test value:"%s"' % (
- repr(rec),
- repr(inParam),
- )
- # test that slices of rows work
- slice1 = tuple(rec[:-1])
- slice2 = tuple(inParam[0:2])
- assert slice1 == slice2, 'returned value:"%s" != test value:"%s"' % (
- repr(slice1),
- repr(slice2),
- )
- # now test named column retrieval
- assert rec["fldTwo"] == inParam[0]
- assert rec.fldThree == inParam[1]
- assert rec.fldFour == inParam[2]
- # test array operation
- # note that the fields vv vv vv are out of order
- crsr.execute("select fldThree,fldFour,fldTwo from xx_%s" % config.tmp)
- recs = crsr.fetchall()
- assert recs[1][0] == 103
- assert recs[0][1] == 4
- assert recs[1]["fldFour"] == 104
- assert recs[0, 0] == 3
- assert recs[0, "fldTwo"] == 2
- assert recs[1, 2] == 102
- for i in range(1):
- for j in range(2):
- assert recs[i][j] == recs[i, j]
-
- def testFormatParamstyle(self):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- conn.paramstyle = "format" # test nonstandard use of paramstyle
- crsr = conn.cursor()
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldData varchar(10),
- fldConst varchar(30))
- """
- % config.tmp
- )
- crsr.execute(tabdef)
-
- inputs = ["one", "two", "three"]
- fldId = 2
- for inParam in inputs:
- fldId += 1
- sql = (
- "INSERT INTO xx_"
- + config.tmp
- + " (fldId,fldConst,fldData) VALUES (%s,'thi%s :may cause? trouble', %s)"
- )
- try:
- crsr.execute(sql, (fldId, inParam))
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldData, fldConst FROM xx_" + config.tmp + " WHERE %s=fldID",
- [fldId],
- )
- rec = crsr.fetchone()
- self.assertEqual(
- rec[0],
- inParam,
- 'returned value:"%s" != test value:"%s"' % (rec[0], inParam),
- )
- self.assertEqual(rec[1], "thi%s :may cause? trouble")
-
- # now try an operation with a "%s" as part of a literal
- sel = (
- "insert into xx_" + config.tmp + " (fldId,fldData) VALUES (%s,'four%sfive')"
- )
- params = (20,)
- crsr.execute(sel, params)
-
- # test the .query implementation
- assert "(?," in crsr.query, 'expected:"%s" in "%s"' % ("(?,", crsr.query)
- # test the .command attribute
- assert crsr.command == sel, 'expected:"%s" but found "%s"' % (sel, crsr.command)
-
- # test the .parameters attribute
- if not self.remote: # parameter list will be altered in transit
- self.assertEqual(crsr.parameters, params)
- # now make sure the data made it
- crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=20" % config.tmp)
- rec = crsr.fetchone()
- self.assertEqual(rec[0], "four%sfive")
-
- def testNamedParamstyle(self):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- crsr = conn.cursor()
- crsr.paramstyle = "named" # test nonstandard use of paramstyle
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldData varchar(10))
- """
- % config.tmp
- )
- crsr.execute(tabdef)
-
- inputs = ["four", "five", "six"]
- fldId = 10
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_%s (fldId,fldData) VALUES (:Id,:f_Val)"
- % config.tmp,
- {"f_Val": inParam, "Id": fldId},
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldData FROM xx_%s WHERE fldID=:Id" % config.tmp, {"Id": fldId}
- )
- rec = crsr.fetchone()
- self.assertEqual(
- rec[0],
- inParam,
- 'returned value:"%s" != test value:"%s"' % (rec[0], inParam),
- )
- # now a test with a ":" as part of a literal
- crsr.execute(
- "insert into xx_%s (fldId,fldData) VALUES (:xyz,'six:five')" % config.tmp,
- {"xyz": 30},
- )
- crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp)
- rec = crsr.fetchone()
- self.assertEqual(rec[0], "six:five")
-
- def testPyformatParamstyle(self):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- crsr = conn.cursor()
- crsr.paramstyle = "pyformat" # test nonstandard use of paramstyle
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldData varchar(10))
- """
- % config.tmp
- )
- crsr.execute(tabdef)
-
- inputs = ["four", "five", "six"]
- fldId = 10
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_%s (fldId,fldData) VALUES (%%(Id)s,%%(f_Val)s)"
- % config.tmp,
- {"f_Val": inParam, "Id": fldId},
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldData FROM xx_%s WHERE fldID=%%(Id)s" % config.tmp,
- {"Id": fldId},
- )
- rec = crsr.fetchone()
- self.assertEqual(
- rec[0],
- inParam,
- 'returned value:"%s" != test value:"%s"' % (rec[0], inParam),
- )
- # now a test with a "%" as part of a literal
- crsr.execute(
- "insert into xx_%s (fldId,fldData) VALUES (%%(xyz)s,'six%%five')"
- % config.tmp,
- {"xyz": 30},
- )
- crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp)
- rec = crsr.fetchone()
- self.assertEqual(rec[0], "six%five")
-
- def testAutomaticParamstyle(self):
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- conn.paramstyle = "dynamic" # test nonstandard use of paramstyle
- crsr = conn.cursor()
- tabdef = (
- """
- CREATE TABLE xx_%s (
- fldId integer NOT NULL,
- fldData varchar(10),
- fldConst varchar(30))
- """
- % config.tmp
- )
- crsr.execute(tabdef)
- inputs = ["one", "two", "three"]
- fldId = 2
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_"
- + config.tmp
- + " (fldId,fldConst,fldData) VALUES (?,'thi%s :may cause? troub:1e', ?)",
- (fldId, inParam),
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- trouble = "thi%s :may cause? troub:1e"
- crsr.execute(
- "SELECT fldData, fldConst FROM xx_" + config.tmp + " WHERE ?=fldID",
- [fldId],
- )
- rec = crsr.fetchone()
- self.assertEqual(
- rec[0],
- inParam,
- 'returned value:"%s" != test value:"%s"' % (rec[0], inParam),
- )
- self.assertEqual(rec[1], trouble)
- # inputs = [u'four',u'five',u'six']
- fldId = 10
- for inParam in inputs:
- fldId += 1
- try:
- crsr.execute(
- "INSERT INTO xx_%s (fldId,fldData) VALUES (:Id,:f_Val)"
- % config.tmp,
- {"f_Val": inParam, "Id": fldId},
- )
- except:
- if self.remote:
- for message in crsr.messages:
- print(message)
- else:
- conn.printADOerrors()
- raise
- crsr.execute(
- "SELECT fldData FROM xx_%s WHERE :Id=fldID" % config.tmp, {"Id": fldId}
- )
- rec = crsr.fetchone()
- self.assertEqual(
- rec[0],
- inParam,
- 'returned value:"%s" != test value:"%s"' % (rec[0], inParam),
- )
- # now a test with a ":" as part of a literal -- and use a prepared query
- ppdcmd = (
- "insert into xx_%s (fldId,fldData) VALUES (:xyz,'six:five')" % config.tmp
- )
- crsr.prepare(ppdcmd)
- crsr.execute(ppdcmd, {"xyz": 30})
- crsr.execute("SELECT fldData FROM xx_%s WHERE fldID=30" % config.tmp)
- rec = crsr.fetchone()
- self.assertEqual(rec[0], "six:five")
-
- def testRollBack(self):
- conn = self.getConnection()
- crsr = conn.cursor()
- assert not crsr.connection.autocommit, "Unexpected beginning condition"
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.connection.commit() # commit the first bunch
-
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp)
-
- selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp
- crsr.execute(selectSql)
- rs = crsr.fetchall()
- assert len(rs) == 1
- self.conn.rollback()
- crsr.execute(selectSql)
- assert (
- crsr.fetchone() == None
- ), "cursor.fetchone should return None if a query retrieves no rows"
- crsr.execute("SELECT fldData from xx_%s" % config.tmp)
- rs = crsr.fetchall()
- assert len(rs) == 9, "the original records should still be present"
- self.helpRollbackTblTemp()
-
- def testCommit(self):
- try:
- con2 = self.getAnotherConnection()
- except NotImplementedError:
- return # should be "SKIP" for ACCESS
- assert not con2.autocommit, "default should be manual commit"
- crsr = con2.cursor()
- self.helpCreateAndPopulateTableTemp(crsr)
-
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp)
- con2.commit()
-
- selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp
- crsr.execute(selectSql)
- rs = crsr.fetchall()
- assert len(rs) == 1
- crsr.close()
- con2.close()
- conn = self.getConnection()
- crsr = self.getCursor()
- with conn.cursor() as crsr:
- crsr.execute(selectSql)
- rs = crsr.fetchall()
- assert len(rs) == 1
- assert rs[0][0] == 100
- self.helpRollbackTblTemp()
-
- def testAutoRollback(self):
- try:
- con2 = self.getAnotherConnection()
- except NotImplementedError:
- return # should be "SKIP" for ACCESS
- assert not con2.autocommit, "unexpected beginning condition"
- crsr = con2.cursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp)
- selectSql = "SELECT fldData FROM xx_%s WHERE fldData=100" % config.tmp
- crsr.execute(selectSql)
- rs = crsr.fetchall()
- assert len(rs) == 1
- crsr.close()
- con2.close()
- crsr = self.getCursor()
- try:
- crsr.execute(
- selectSql
- ) # closing the connection should have forced rollback
- row = crsr.fetchone()
- except api.DatabaseError:
- row = None # if the entire table disappeared the rollback was perfect and the test passed
- assert row == None, (
- "cursor.fetchone should return None if a query retrieves no rows. Got %s"
- % repr(row)
- )
- self.helpRollbackTblTemp()
-
- def testAutoCommit(self):
- try:
- ac_conn = self.getAnotherConnection({"autocommit": True})
- except NotImplementedError:
- return # should be "SKIP" for ACCESS
- crsr = ac_conn.cursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp)
- crsr.close()
- with self.getCursor() as crsr:
- selectSql = "SELECT fldData from xx_%s" % config.tmp
- crsr.execute(
- selectSql
- ) # closing the connection should _not_ have forced rollback
- rs = crsr.fetchall()
- assert len(rs) == 10, "all records should still be present"
- ac_conn.close()
- self.helpRollbackTblTemp()
-
- def testSwitchedAutoCommit(self):
- try:
- ac_conn = self.getAnotherConnection()
- except NotImplementedError:
- return # should be "SKIP" for ACCESS
- ac_conn.autocommit = True
- crsr = ac_conn.cursor()
- self.helpCreateAndPopulateTableTemp(crsr)
- crsr.execute("INSERT INTO xx_%s (fldData) VALUES(100)" % config.tmp)
- crsr.close()
- conn = self.getConnection()
- ac_conn.close()
- with self.getCursor() as crsr:
- selectSql = "SELECT fldData from xx_%s" % config.tmp
- crsr.execute(
- selectSql
- ) # closing the connection should _not_ have forced rollback
- rs = crsr.fetchall()
- assert len(rs) == 10, "all records should still be present"
- self.helpRollbackTblTemp()
-
- def testExtendedTypeHandling(self):
- class XtendString(str):
- pass
-
- class XtendInt(int):
- pass
-
- class XtendFloat(float):
- pass
-
- xs = XtendString(randomstring(30))
- xi = XtendInt(random.randint(-100, 500))
- xf = XtendFloat(random.random())
- self.helpForceDropOnTblTemp()
- conn = self.getConnection()
- crsr = conn.cursor()
- tabdef = (
- """
- CREATE TABLE xx_%s (
- s VARCHAR(40) NOT NULL,
- i INTEGER NOT NULL,
- f REAL NOT NULL)"""
- % config.tmp
- )
- crsr.execute(tabdef)
- crsr.execute(
- "INSERT INTO xx_%s (s, i, f) VALUES (?, ?, ?)" % config.tmp, (xs, xi, xf)
- )
- crsr.close()
- conn = self.getConnection()
- with self.getCursor() as crsr:
- selectSql = "SELECT s, i, f from xx_%s" % config.tmp
- crsr.execute(
- selectSql
- ) # closing the connection should _not_ have forced rollback
- row = crsr.fetchone()
- self.assertEqual(row.s, xs)
- self.assertEqual(row.i, xi)
- self.assertAlmostEqual(row.f, xf)
- self.helpRollbackTblTemp()
-
-
- class TestADOwithSQLServer(CommonDBTests):
- def setUp(self):
- self.conn = config.dbSqlServerconnect(
- *config.connStrSQLServer[0], **config.connStrSQLServer[1]
- )
- self.conn.timeout = 30 # turn timeout back up
- self.engine = "MSSQL"
- self.db = config.dbSqlServerconnect
- self.remote = config.connStrSQLServer[2]
-
- def tearDown(self):
- try:
- self.conn.rollback()
- except:
- pass
- try:
- self.conn.close()
- except:
- pass
- self.conn = None
-
- def getConnection(self):
- return self.conn
-
- def getAnotherConnection(self, addkeys=None):
- keys = dict(config.connStrSQLServer[1])
- if addkeys:
- keys.update(addkeys)
- return config.dbSqlServerconnect(*config.connStrSQLServer[0], **keys)
-
- def testVariableReturningStoredProcedure(self):
- crsr = self.conn.cursor()
- spdef = """
- CREATE PROCEDURE sp_DeleteMeOnlyForTesting
- @theInput varchar(50),
- @theOtherInput varchar(50),
- @theOutput varchar(100) OUTPUT
- AS
- SET @theOutput=@theInput+@theOtherInput
- """
- try:
- crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting")
- self.conn.commit()
- except: # Make sure it is empty
- pass
- crsr.execute(spdef)
-
- retvalues = crsr.callproc(
- "sp_DeleteMeOnlyForTesting", ("Dodsworth", "Anne", " ")
- )
- assert retvalues[0] == "Dodsworth", '%s is not "Dodsworth"' % repr(retvalues[0])
- assert retvalues[1] == "Anne", '%s is not "Anne"' % repr(retvalues[1])
- assert retvalues[2] == "DodsworthAnne", '%s is not "DodsworthAnne"' % repr(
- retvalues[2]
- )
- self.conn.rollback()
-
- def testMultipleSetReturn(self):
- crsr = self.getCursor()
- self.helpCreateAndPopulateTableTemp(crsr)
-
- spdef = """
- CREATE PROCEDURE sp_DeleteMe_OnlyForTesting
- AS
- SELECT fldData FROM xx_%s ORDER BY fldData ASC
- SELECT fldData From xx_%s where fldData = -9999
- SELECT fldData FROM xx_%s ORDER BY fldData DESC
- """ % (
- config.tmp,
- config.tmp,
- config.tmp,
- )
- try:
- crsr.execute("DROP PROCEDURE sp_DeleteMe_OnlyForTesting")
- self.conn.commit()
- except: # Make sure it is empty
- pass
- crsr.execute(spdef)
-
- retvalues = crsr.callproc("sp_DeleteMe_OnlyForTesting")
- row = crsr.fetchone()
- self.assertEqual(row[0], 0)
- assert crsr.nextset() == True, "Operation should succeed"
- assert not crsr.fetchall(), "Should be an empty second set"
- assert crsr.nextset() == True, "third set should be present"
- rowdesc = crsr.fetchall()
- self.assertEqual(rowdesc[0][0], 8)
- assert crsr.nextset() == None, "No more return sets, should return None"
-
- self.helpRollbackTblTemp()
-
- def testDatetimeProcedureParameter(self):
- crsr = self.conn.cursor()
- spdef = """
- CREATE PROCEDURE sp_DeleteMeOnlyForTesting
- @theInput DATETIME,
- @theOtherInput varchar(50),
- @theOutput varchar(100) OUTPUT
- AS
- SET @theOutput = CONVERT(CHARACTER(20), @theInput, 0) + @theOtherInput
- """
- try:
- crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting")
- self.conn.commit()
- except: # Make sure it is empty
- pass
- crsr.execute(spdef)
-
- result = crsr.callproc(
- "sp_DeleteMeOnlyForTesting",
- [adodbapi.Timestamp(2014, 12, 25, 0, 1, 0), "Beep", " " * 30],
- )
-
- assert result[2] == "Dec 25 2014 12:01AM Beep", 'value was="%s"' % result[2]
- self.conn.rollback()
-
- def testIncorrectStoredProcedureParameter(self):
- crsr = self.conn.cursor()
- spdef = """
- CREATE PROCEDURE sp_DeleteMeOnlyForTesting
- @theInput DATETIME,
- @theOtherInput varchar(50),
- @theOutput varchar(100) OUTPUT
- AS
- SET @theOutput = CONVERT(CHARACTER(20), @theInput) + @theOtherInput
- """
- try:
- crsr.execute("DROP PROCEDURE sp_DeleteMeOnlyForTesting")
- self.conn.commit()
- except: # Make sure it is empty
- pass
- crsr.execute(spdef)
-
- # calling the sproc with a string for the first parameter where a DateTime is expected
- result = tryconnection.try_operation_with_expected_exception(
- (api.DataError, api.DatabaseError),
- crsr.callproc,
- ["sp_DeleteMeOnlyForTesting"],
- {"parameters": ["this is wrong", "Anne", "not Alice"]},
- )
- if result[0]: # the expected exception was raised
- assert "@theInput" in str(result[1]) or "DatabaseError" in str(
- result
- ), "Identifies the wrong erroneous parameter"
- else:
- assert result[0], result[1] # incorrect or no exception
- self.conn.rollback()
-
-
- class TestADOwithAccessDB(CommonDBTests):
- def setUp(self):
- self.conn = config.dbAccessconnect(
- *config.connStrAccess[0], **config.connStrAccess[1]
- )
- self.conn.timeout = 30 # turn timeout back up
- self.engine = "ACCESS"
- self.db = config.dbAccessconnect
- self.remote = config.connStrAccess[2]
-
- def tearDown(self):
- try:
- self.conn.rollback()
- except:
- pass
- try:
- self.conn.close()
- except:
- pass
- self.conn = None
-
- def getConnection(self):
- return self.conn
-
- def getAnotherConnection(self, addkeys=None):
- raise NotImplementedError("Jet cannot use a second connection to the database")
-
- def testOkConnect(self):
- c = self.db(*config.connStrAccess[0], **config.connStrAccess[1])
- assert c != None
- c.close()
-
-
- class TestADOwithMySql(CommonDBTests):
- def setUp(self):
- self.conn = config.dbMySqlconnect(
- *config.connStrMySql[0], **config.connStrMySql[1]
- )
- self.conn.timeout = 30 # turn timeout back up
- self.engine = "MySQL"
- self.db = config.dbMySqlconnect
- self.remote = config.connStrMySql[2]
-
- def tearDown(self):
- try:
- self.conn.rollback()
- except:
- pass
- try:
- self.conn.close()
- except:
- pass
- self.conn = None
-
- def getConnection(self):
- return self.conn
-
- def getAnotherConnection(self, addkeys=None):
- keys = dict(config.connStrMySql[1])
- if addkeys:
- keys.update(addkeys)
- return config.dbMySqlconnect(*config.connStrMySql[0], **keys)
-
- def testOkConnect(self):
- c = self.db(*config.connStrMySql[0], **config.connStrMySql[1])
- assert c != None
-
- # def testStoredProcedure(self):
- # crsr=self.conn.cursor()
- # try:
- # crsr.execute("DROP PROCEDURE DeleteMeOnlyForTesting")
- # self.conn.commit()
- # except: #Make sure it is empty
- # pass
- # spdef= """
- # DELIMITER $$
- # CREATE PROCEDURE DeleteMeOnlyForTesting (onein CHAR(10), twoin CHAR(10), OUT theout CHAR(20))
- # DETERMINISTIC
- # BEGIN
- # SET theout = onein //|| twoin;
- # /* (SELECT 'a small string' as result; */
- # END $$
- # """
- #
- # crsr.execute(spdef)
- #
- # retvalues=crsr.callproc('DeleteMeOnlyForTesting',('Dodsworth','Anne',' '))
- # print 'return value (mysql)=',repr(crsr.returnValue) ###
- # assert retvalues[0]=='Dodsworth', '%s is not "Dodsworth"'%repr(retvalues[0])
- # assert retvalues[1]=='Anne','%s is not "Anne"'%repr(retvalues[1])
- # assert retvalues[2]=='DodsworthAnne','%s is not "DodsworthAnne"'%repr(retvalues[2])
- #
- # try:
- # crsr.execute("DROP PROCEDURE, DeleteMeOnlyForTesting")
- # self.conn.commit()
- # except: #Make sure it is empty
- # pass
-
-
- class TestADOwithPostgres(CommonDBTests):
- def setUp(self):
- self.conn = config.dbPostgresConnect(
- *config.connStrPostgres[0], **config.connStrPostgres[1]
- )
- self.conn.timeout = 30 # turn timeout back up
- self.engine = "PostgreSQL"
- self.db = config.dbPostgresConnect
- self.remote = config.connStrPostgres[2]
-
- def tearDown(self):
- try:
- self.conn.rollback()
- except:
- pass
- try:
- self.conn.close()
- except:
- pass
- self.conn = None
-
- def getConnection(self):
- return self.conn
-
- def getAnotherConnection(self, addkeys=None):
- keys = dict(config.connStrPostgres[1])
- if addkeys:
- keys.update(addkeys)
- return config.dbPostgresConnect(*config.connStrPostgres[0], **keys)
-
- def testOkConnect(self):
- c = self.db(*config.connStrPostgres[0], **config.connStrPostgres[1])
- assert c != None
-
- # def testStoredProcedure(self):
- # crsr=self.conn.cursor()
- # spdef= """
- # CREATE OR REPLACE FUNCTION DeleteMeOnlyForTesting (text, text)
- # RETURNS text AS $funk$
- # BEGIN
- # RETURN $1 || $2;
- # END;
- # $funk$
- # LANGUAGE SQL;
- # """
- #
- # crsr.execute(spdef)
- # retvalues = crsr.callproc('DeleteMeOnlyForTesting',('Dodsworth','Anne',' '))
- # ### print 'return value (pg)=',repr(crsr.returnValue) ###
- # assert retvalues[0]=='Dodsworth', '%s is not "Dodsworth"'%repr(retvalues[0])
- # assert retvalues[1]=='Anne','%s is not "Anne"'%repr(retvalues[1])
- # assert retvalues[2]=='Dodsworth Anne','%s is not "Dodsworth Anne"'%repr(retvalues[2])
- # self.conn.rollback()
- # try:
- # crsr.execute("DROP PROCEDURE, DeleteMeOnlyForTesting")
- # self.conn.commit()
- # except: #Make sure it is empty
- # pass
-
-
- class TimeConverterInterfaceTest(unittest.TestCase):
- def testIDate(self):
- assert self.tc.Date(1990, 2, 2)
-
- def testITime(self):
- assert self.tc.Time(13, 2, 2)
-
- def testITimestamp(self):
- assert self.tc.Timestamp(1990, 2, 2, 13, 2, 1)
-
- def testIDateObjectFromCOMDate(self):
- assert self.tc.DateObjectFromCOMDate(37435.7604282)
-
- def testICOMDate(self):
- assert hasattr(self.tc, "COMDate")
-
- def testExactDate(self):
- d = self.tc.Date(1994, 11, 15)
- comDate = self.tc.COMDate(d)
- correct = 34653.0
- assert comDate == correct, comDate
-
- def testExactTimestamp(self):
- d = self.tc.Timestamp(1994, 11, 15, 12, 0, 0)
- comDate = self.tc.COMDate(d)
- correct = 34653.5
- self.assertEqual(comDate, correct)
-
- d = self.tc.Timestamp(2003, 5, 6, 14, 15, 17)
- comDate = self.tc.COMDate(d)
- correct = 37747.593946759262
- self.assertEqual(comDate, correct)
-
- def testIsoFormat(self):
- d = self.tc.Timestamp(1994, 11, 15, 12, 3, 10)
- iso = self.tc.DateObjectToIsoFormatString(d)
- self.assertEqual(str(iso[:19]), "1994-11-15 12:03:10")
-
- dt = self.tc.Date(2003, 5, 2)
- iso = self.tc.DateObjectToIsoFormatString(dt)
- self.assertEqual(str(iso[:10]), "2003-05-02")
-
-
- if config.doMxDateTimeTest:
- import mx.DateTime
-
-
- class TestMXDateTimeConverter(TimeConverterInterfaceTest):
- def setUp(self):
- self.tc = api.mxDateTimeConverter()
-
- def testCOMDate(self):
- t = mx.DateTime.DateTime(2002, 6, 28, 18, 15, 2)
- cmd = self.tc.COMDate(t)
- assert cmd == t.COMDate()
-
- def testDateObjectFromCOMDate(self):
- cmd = self.tc.DateObjectFromCOMDate(37435.7604282)
- t = mx.DateTime.DateTime(2002, 6, 28, 18, 15, 0)
- t2 = mx.DateTime.DateTime(2002, 6, 28, 18, 15, 2)
- assert t2 > cmd > t
-
- def testDate(self):
- assert mx.DateTime.Date(1980, 11, 4) == self.tc.Date(1980, 11, 4)
-
- def testTime(self):
- assert mx.DateTime.Time(13, 11, 4) == self.tc.Time(13, 11, 4)
-
- def testTimestamp(self):
- t = mx.DateTime.DateTime(2002, 6, 28, 18, 15, 1)
- obj = self.tc.Timestamp(2002, 6, 28, 18, 15, 1)
- assert t == obj
-
-
- import time
-
-
- class TestPythonTimeConverter(TimeConverterInterfaceTest):
- def setUp(self):
- self.tc = api.pythonTimeConverter()
-
- def testCOMDate(self):
- mk = time.mktime((2002, 6, 28, 18, 15, 1, 4, 31 + 28 + 31 + 30 + 31 + 28, -1))
- t = time.localtime(mk)
- # Fri, 28 Jun 2002 18:15:01 +0000
- cmd = self.tc.COMDate(t)
- assert abs(cmd - 37435.7604282) < 1.0 / 24, "%f more than an hour wrong" % cmd
-
- def testDateObjectFromCOMDate(self):
- cmd = self.tc.DateObjectFromCOMDate(37435.7604282)
- t1 = time.gmtime(
- time.mktime((2002, 6, 28, 0, 14, 1, 4, 31 + 28 + 31 + 30 + 31 + 28, -1))
- )
- # there are errors in the implementation of gmtime which we ignore
- t2 = time.gmtime(
- time.mktime((2002, 6, 29, 12, 14, 2, 4, 31 + 28 + 31 + 30 + 31 + 28, -1))
- )
- assert t1 < cmd < t2, '"%s" should be about 2002-6-28 12:15:01' % repr(cmd)
-
- def testDate(self):
- t1 = time.mktime((2002, 6, 28, 18, 15, 1, 4, 31 + 28 + 31 + 30 + 31 + 30, 0))
- t2 = time.mktime((2002, 6, 30, 18, 15, 1, 4, 31 + 28 + 31 + 30 + 31 + 28, 0))
- obj = self.tc.Date(2002, 6, 29)
- assert t1 < time.mktime(obj) < t2, obj
-
- def testTime(self):
- self.assertEqual(
- self.tc.Time(18, 15, 2), time.gmtime(18 * 60 * 60 + 15 * 60 + 2)
- )
-
- def testTimestamp(self):
- t1 = time.localtime(
- time.mktime((2002, 6, 28, 18, 14, 1, 4, 31 + 28 + 31 + 30 + 31 + 28, -1))
- )
- t2 = time.localtime(
- time.mktime((2002, 6, 28, 18, 16, 1, 4, 31 + 28 + 31 + 30 + 31 + 28, -1))
- )
- obj = self.tc.Timestamp(2002, 6, 28, 18, 15, 2)
- assert t1 < obj < t2, obj
-
-
- class TestPythonDateTimeConverter(TimeConverterInterfaceTest):
- def setUp(self):
- self.tc = api.pythonDateTimeConverter()
-
- def testCOMDate(self):
- t = datetime.datetime(2002, 6, 28, 18, 15, 1)
- # Fri, 28 Jun 2002 18:15:01 +0000
- cmd = self.tc.COMDate(t)
- assert abs(cmd - 37435.7604282) < 1.0 / 24, "more than an hour wrong"
-
- def testDateObjectFromCOMDate(self):
- cmd = self.tc.DateObjectFromCOMDate(37435.7604282)
- t1 = datetime.datetime(2002, 6, 28, 18, 14, 1)
- t2 = datetime.datetime(2002, 6, 28, 18, 16, 1)
- assert t1 < cmd < t2, cmd
-
- tx = datetime.datetime(
- 2002, 6, 28, 18, 14, 1, 900000
- ) # testing that microseconds don't become milliseconds
- c1 = self.tc.DateObjectFromCOMDate(self.tc.COMDate(tx))
- assert t1 < c1 < t2, c1
-
- def testDate(self):
- t1 = datetime.date(2002, 6, 28)
- t2 = datetime.date(2002, 6, 30)
- obj = self.tc.Date(2002, 6, 29)
- assert t1 < obj < t2, obj
-
- def testTime(self):
- self.assertEqual(self.tc.Time(18, 15, 2).isoformat()[:8], "18:15:02")
-
- def testTimestamp(self):
- t1 = datetime.datetime(2002, 6, 28, 18, 14, 1)
- t2 = datetime.datetime(2002, 6, 28, 18, 16, 1)
- obj = self.tc.Timestamp(2002, 6, 28, 18, 15, 2)
- assert t1 < obj < t2, obj
-
-
- suites = []
- suites.append(unittest.makeSuite(TestPythonDateTimeConverter, "test"))
- if config.doMxDateTimeTest:
- suites.append(unittest.makeSuite(TestMXDateTimeConverter, "test"))
- if config.doTimeTest:
- suites.append(unittest.makeSuite(TestPythonTimeConverter, "test"))
-
- if config.doAccessTest:
- suites.append(unittest.makeSuite(TestADOwithAccessDB, "test"))
- if config.doSqlServerTest:
- suites.append(unittest.makeSuite(TestADOwithSQLServer, "test"))
- if config.doMySqlTest:
- suites.append(unittest.makeSuite(TestADOwithMySql, "test"))
- if config.doPostgresTest:
- suites.append(unittest.makeSuite(TestADOwithPostgres, "test"))
-
-
- class cleanup_manager(object):
- def __enter__(self):
- pass
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- config.cleanup(config.testfolder, config.mdb_name)
-
-
- suite = unittest.TestSuite(suites)
- if __name__ == "__main__":
- mysuite = copy.deepcopy(suite)
- with cleanup_manager():
- defaultDateConverter = adodbapi.dateconverter
- print(__doc__)
- print("Default Date Converter is %s" % (defaultDateConverter,))
- dateconverter = defaultDateConverter
- tag = "datetime"
- unittest.TextTestRunner().run(mysuite)
-
- if config.iterateOverTimeTests:
- for test, dateconverter, tag in (
- (config.doTimeTest, api.pythonTimeConverter, "pythontime"),
- (config.doMxDateTimeTest, api.mxDateTimeConverter, "mx"),
- ):
- if test:
- mysuite = copy.deepcopy(
- suite
- ) # work around a side effect of unittest.TextTestRunner
- adodbapi.adodbapi.dateconverter = dateconverter()
- print("Changed dateconverter to ")
- print(adodbapi.adodbapi.dateconverter)
- unittest.TextTestRunner().run(mysuite)
|