You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by el...@apache.org on 2018/10/05 23:02:48 UTC
[23/40] phoenix git commit: PHOENIX-4688 Support SPNEGO for python
driver via requests-kerberos
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/phoenixdb/types.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/phoenixdb/types.py b/python/phoenixdb/phoenixdb/types.py
new file mode 100644
index 0000000..f41355a
--- /dev/null
+++ b/python/phoenixdb/phoenixdb/types.py
@@ -0,0 +1,202 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import time
+import datetime
+from decimal import Decimal
+from phoenixdb.avatica.proto import common_pb2
+
+__all__ = [
+ 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', 'TimestampFromTicks',
+ 'Binary', 'STRING', 'BINARY', 'NUMBER', 'DATETIME', 'ROWID', 'BOOLEAN',
+ 'JAVA_CLASSES', 'JAVA_CLASSES_MAP', 'TypeHelper',
+]
+
+
+def Date(year, month, day):
+ """Constructs an object holding a date value."""
+ return datetime.date(year, month, day)
+
+
+def Time(hour, minute, second):
+ """Constructs an object holding a time value."""
+ return datetime.time(hour, minute, second)
+
+
+def Timestamp(year, month, day, hour, minute, second):
+ """Constructs an object holding a datetime/timestamp value."""
+ return datetime.datetime(year, month, day, hour, minute, second)
+
+
+def DateFromTicks(ticks):
+ """Constructs an object holding a date value from the given UNIX timestamp."""
+ return Date(*time.localtime(ticks)[:3])
+
+
+def TimeFromTicks(ticks):
+ """Constructs an object holding a time value from the given UNIX timestamp."""
+ return Time(*time.localtime(ticks)[3:6])
+
+
+def TimestampFromTicks(ticks):
+ """Constructs an object holding a datetime/timestamp value from the given UNIX timestamp."""
+ return Timestamp(*time.localtime(ticks)[:6])
+
+
+def Binary(value):
+ """Constructs an object capable of holding a binary (long) string value."""
+ return bytes(value)
+
+
+def time_from_java_sql_time(n):
+ dt = datetime.datetime(1970, 1, 1) + datetime.timedelta(milliseconds=n)
+ return dt.time()
+
+
+def time_to_java_sql_time(t):
+ return ((t.hour * 60 + t.minute) * 60 + t.second) * 1000 + t.microsecond // 1000
+
+
+def date_from_java_sql_date(n):
+ return datetime.date(1970, 1, 1) + datetime.timedelta(days=n)
+
+
+def date_to_java_sql_date(d):
+ if isinstance(d, datetime.datetime):
+ d = d.date()
+ td = d - datetime.date(1970, 1, 1)
+ return td.days
+
+
+def datetime_from_java_sql_timestamp(n):
+ return datetime.datetime(1970, 1, 1) + datetime.timedelta(milliseconds=n)
+
+
+def datetime_to_java_sql_timestamp(d):
+ td = d - datetime.datetime(1970, 1, 1)
+ return td.microseconds // 1000 + (td.seconds + td.days * 24 * 3600) * 1000
+
+
+class ColumnType(object):
+
+ def __init__(self, eq_types):
+ self.eq_types = tuple(eq_types)
+ self.eq_types_set = set(eq_types)
+
+ def __eq__(self, other):
+ return other in self.eq_types_set
+
+ def __cmp__(self, other):
+ if other in self.eq_types_set:
+ return 0
+ if other < self.eq_types:
+ return 1
+ else:
+ return -1
+
+
+STRING = ColumnType(['VARCHAR', 'CHAR'])
+"""Type object that can be used to describe string-based columns."""
+
+BINARY = ColumnType(['BINARY', 'VARBINARY'])
+"""Type object that can be used to describe (long) binary columns."""
+
+NUMBER = ColumnType([
+ 'INTEGER', 'UNSIGNED_INT', 'BIGINT', 'UNSIGNED_LONG', 'TINYINT', 'UNSIGNED_TINYINT',
+ 'SMALLINT', 'UNSIGNED_SMALLINT', 'FLOAT', 'UNSIGNED_FLOAT', 'DOUBLE', 'UNSIGNED_DOUBLE', 'DECIMAL'
+])
+"""Type object that can be used to describe numeric columns."""
+
+DATETIME = ColumnType(['TIME', 'DATE', 'TIMESTAMP', 'UNSIGNED_TIME', 'UNSIGNED_DATE', 'UNSIGNED_TIMESTAMP'])
+"""Type object that can be used to describe date/time columns."""
+
+ROWID = ColumnType([])
+"""Only implemented for DB API 2.0 compatibility, not used."""
+
+BOOLEAN = ColumnType(['BOOLEAN'])
+"""Type object that can be used to describe boolean columns. This is a phoenixdb-specific extension."""
+
+
+# XXX ARRAY
+
+if sys.version_info[0] < 3:
+ _long = long # noqa: F821
+else:
+ _long = int
+
+JAVA_CLASSES = {
+ 'bool_value': [
+ ('java.lang.Boolean', common_pb2.BOOLEAN, None, None),
+ ],
+ 'string_value': [
+ ('java.lang.Character', common_pb2.CHARACTER, None, None),
+ ('java.lang.String', common_pb2.STRING, None, None),
+ ('java.math.BigDecimal', common_pb2.BIG_DECIMAL, str, Decimal),
+ ],
+ 'number_value': [
+ ('java.lang.Integer', common_pb2.INTEGER, None, int),
+ ('java.lang.Short', common_pb2.SHORT, None, int),
+ ('java.lang.Long', common_pb2.LONG, None, _long),
+ ('java.lang.Byte', common_pb2.BYTE, None, int),
+ ('java.sql.Time', common_pb2.JAVA_SQL_TIME, time_to_java_sql_time, time_from_java_sql_time),
+ ('java.sql.Date', common_pb2.JAVA_SQL_DATE, date_to_java_sql_date, date_from_java_sql_date),
+ ('java.sql.Timestamp', common_pb2.JAVA_SQL_TIMESTAMP, datetime_to_java_sql_timestamp, datetime_from_java_sql_timestamp),
+ ],
+ 'bytes_value': [
+ ('[B', common_pb2.BYTE_STRING, Binary, None),
+ ],
+ 'double_value': [
+ # if common_pb2.FLOAT is used, incorrect values are sent
+ ('java.lang.Float', common_pb2.DOUBLE, float, float),
+ ('java.lang.Double', common_pb2.DOUBLE, float, float),
+ ]
+}
+"""Groups of Java classes."""
+
+JAVA_CLASSES_MAP = dict((v[0], (k, v[1], v[2], v[3])) for k in JAVA_CLASSES for v in JAVA_CLASSES[k])
+"""Flips the available types to allow for faster lookup by Java class.
+
+This mapping should be structured as:
+ {
+ 'java.math.BigDecimal': ('string_value', common_pb2.BIG_DECIMAL, str, Decimal),),
+ ...
+ '<java class>': (<field_name>, <Rep enum>, <mutate_to function>, <cast_from function>),
+ }
+"""
+
+
+class TypeHelper(object):
+ @staticmethod
+ def from_class(klass):
+ """Retrieves a Rep and functions to cast to/from based on the Java class.
+
+ :param klass:
+ The string of the Java class for the column or parameter.
+
+ :returns: tuple ``(field_name, rep, mutate_to, cast_from)``
+ WHERE
+ ``field_name`` is the attribute in ``common_pb2.TypedValue``
+ ``rep`` is the common_pb2.Rep enum
+ ``mutate_to`` is the function to cast values into Phoenix values, if any
+ ``cast_from`` is the function to cast from the Phoenix value to the Python value, if any
+
+ :raises:
+ NotImplementedError
+ """
+ if klass not in JAVA_CLASSES_MAP:
+ raise NotImplementedError('type {} is not supported'.format(klass))
+
+ return JAVA_CLASSES_MAP[klass]
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/requirements.txt
----------------------------------------------------------------------
diff --git a/python/phoenixdb/requirements.txt b/python/phoenixdb/requirements.txt
new file mode 100644
index 0000000..e6be902
--- /dev/null
+++ b/python/phoenixdb/requirements.txt
@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-e git+https://bitbucket.org/lalinsky/python-sqlline.git#egg=sqlline
+nose
+protobuf>=3.0.0
+sphinx
+flake8
+requests
+../requests-kerberos
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/setup.cfg
----------------------------------------------------------------------
diff --git a/python/phoenixdb/setup.cfg b/python/phoenixdb/setup.cfg
new file mode 100644
index 0000000..ebc28c2
--- /dev/null
+++ b/python/phoenixdb/setup.cfg
@@ -0,0 +1,34 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[nosetests]
+verbosity=2
+testmatch=^test_.+
+where=phoenixdb/tests
+
+[build_sphinx]
+source-dir = doc
+build-dir = doc/build
+all_files = 1
+
+[upload_sphinx]
+upload-dir = doc/build/html
+
+[flake8]
+max-line-length = 140
+exclude =
+ e,e3,env,venv,doc,build,dist,.tox,.idea,
+ ./phoenixdb/tests/dbapi20.py,
+ ./phoenixdb/avatica/proto/*_pb2.py
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/setup.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/setup.py b/python/phoenixdb/setup.py
new file mode 100644
index 0000000..994286a
--- /dev/null
+++ b/python/phoenixdb/setup.py
@@ -0,0 +1,69 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+from setuptools import setup, find_packages
+
+cmdclass = {}
+
+try:
+ from sphinx.setup_command import BuildDoc
+ cmdclass['build_sphinx'] = BuildDoc
+except ImportError:
+ pass
+
+
+def readme():
+ with open('README.rst') as f:
+ return f.read()
+
+
+version = "0.7"
+
+setup(
+ name="phoenixdb",
+ version=version,
+ description="Phoenix database adapter for Python",
+ long_description=readme(),
+ author="Lukas Lalinsky",
+ author_email="lukas@oxygene.sk",
+ url="https://bitbucket.org/lalinsky/python-phoenixdb",
+ license="Apache 2",
+ packages=find_packages(),
+ include_package_data=True,
+ cmdclass=cmdclass,
+ command_options={
+ 'build_sphinx': {
+ 'version': ('setup.py', version),
+ 'release': ('setup.py', version),
+ },
+ },
+ classifiers=[
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ ],
+ install_requires=[
+ 'protobuf>=3.0.0',
+ 'requests',
+ 'requests-kerberos'
+ ]
+)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/__init__.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/__init__.py b/python/phoenixdb/tests/__init__.py
deleted file mode 100644
index ec9a79b..0000000
--- a/python/phoenixdb/tests/__init__.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import unittest
-import phoenixdb
-
-TEST_DB_URL = os.environ.get('PHOENIXDB_TEST_DB_URL')
-
-
-@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
-class DatabaseTestCase(unittest.TestCase):
-
- def setUp(self):
- self.conn = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- self.cleanup_tables = []
-
- def tearDown(self):
- self.doCleanups()
- self.conn.close()
-
- def addTableCleanup(self, name):
- def dropTable():
- with self.conn.cursor() as cursor:
- cursor.execute("DROP TABLE IF EXISTS {}".format(name))
- self.addCleanup(dropTable)
-
- def createTable(self, name, columns):
- with self.conn.cursor() as cursor:
- cursor.execute("DROP TABLE IF EXISTS {}".format(name))
- cursor.execute("CREATE TABLE {} ({})".format(name, columns))
- self.addTableCleanup(name)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/dbapi20.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/dbapi20.py b/python/phoenixdb/tests/dbapi20.py
deleted file mode 100644
index f176400..0000000
--- a/python/phoenixdb/tests/dbapi20.py
+++ /dev/null
@@ -1,857 +0,0 @@
-#!/usr/bin/env python
-
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-''' Python DB API 2.0 driver compliance unit test suite.
-
- This software is Public Domain and may be used without restrictions.
-
- "Now we have booze and barflies entering the discussion, plus rumours of
- DBAs on drugs... and I won't tell you what flashes through my mind each
- time I read the subject line with 'Anal Compliance' in it. All around
- this is turning out to be a thoroughly unwholesome unit test."
-
- -- Ian Bicking
-'''
-
-__version__ = '1.14.3'
-
-import unittest
-import time
-import sys
-
-if sys.version[0] >= '3': #python 3.x
- _BaseException = Exception
- def _failUnless(self, expr, msg=None):
- self.assertTrue(expr, msg)
-else: #python 2.x
- from exceptions import StandardError as _BaseException
- def _failUnless(self, expr, msg=None):
- self.failUnless(expr, msg) ## deprecated since Python 2.6
-
-def str2bytes(sval):
- if sys.version_info < (3,0) and isinstance(sval, str):
- sval = sval.decode("latin1")
- return sval.encode("latin1") #python 3 make unicode into bytes
-
-class DatabaseAPI20Test(unittest.TestCase):
- ''' Test a database self.driver for DB API 2.0 compatibility.
- This implementation tests Gadfly, but the TestCase
- is structured so that other self.drivers can subclass this
- test case to ensure compiliance with the DB-API. It is
- expected that this TestCase may be expanded in the future
- if ambiguities or edge conditions are discovered.
-
- The 'Optional Extensions' are not yet being tested.
-
- self.drivers should subclass this test, overriding setUp, tearDown,
- self.driver, connect_args and connect_kw_args. Class specification
- should be as follows:
-
- import dbapi20
- class mytest(dbapi20.DatabaseAPI20Test):
- [...]
-
- Don't 'import DatabaseAPI20Test from dbapi20', or you will
- confuse the unit tester - just 'import dbapi20'.
- '''
-
- # The self.driver module. This should be the module where the 'connect'
- # method is to be found
- driver = None
- connect_args = () # List of arguments to pass to connect
- connect_kw_args = {} # Keyword arguments for connect
- table_prefix = 'dbapi20test_' # If you need to specify a prefix for tables
-
- ddl1 = 'create table %sbooze (name varchar(20))' % table_prefix
- ddl2 = 'create table %sbarflys (name varchar(20), drink varchar(30))' % table_prefix
- xddl1 = 'drop table %sbooze' % table_prefix
- xddl2 = 'drop table %sbarflys' % table_prefix
- insert = 'insert'
-
- lowerfunc = 'lower' # Name of stored procedure to convert string->lowercase
-
- # Some drivers may need to override these helpers, for example adding
- # a 'commit' after the execute.
- def executeDDL1(self,cursor):
- cursor.execute(self.ddl1)
-
- def executeDDL2(self,cursor):
- cursor.execute(self.ddl2)
-
- def setUp(self):
- ''' self.drivers should override this method to perform required setup
- if any is necessary, such as creating the database.
- '''
- pass
-
- def tearDown(self):
- ''' self.drivers should override this method to perform required cleanup
- if any is necessary, such as deleting the test database.
- The default drops the tables that may be created.
- '''
- try:
- con = self._connect()
- try:
- cur = con.cursor()
- for ddl in (self.xddl1,self.xddl2):
- try:
- cur.execute(ddl)
- con.commit()
- except self.driver.Error:
- # Assume table didn't exist. Other tests will check if
- # execute is busted.
- pass
- finally:
- con.close()
- except _BaseException:
- pass
-
- def _connect(self):
- try:
- r = self.driver.connect(
- *self.connect_args,**self.connect_kw_args
- )
- except AttributeError:
- self.fail("No connect method found in self.driver module")
- return r
-
- def test_connect(self):
- con = self._connect()
- con.close()
-
- def test_apilevel(self):
- try:
- # Must exist
- apilevel = self.driver.apilevel
- # Must equal 2.0
- self.assertEqual(apilevel,'2.0')
- except AttributeError:
- self.fail("Driver doesn't define apilevel")
-
- def test_threadsafety(self):
- try:
- # Must exist
- threadsafety = self.driver.threadsafety
- # Must be a valid value
- _failUnless(self, threadsafety in (0,1,2,3))
- except AttributeError:
- self.fail("Driver doesn't define threadsafety")
-
- def test_paramstyle(self):
- try:
- # Must exist
- paramstyle = self.driver.paramstyle
- # Must be a valid value
- _failUnless(self, paramstyle in (
- 'qmark','numeric','named','format','pyformat'
- ))
- except AttributeError:
- self.fail("Driver doesn't define paramstyle")
-
- def test_Exceptions(self):
- # Make sure required exceptions exist, and are in the
- # defined heirarchy.
- if sys.version[0] == '3': #under Python 3 StardardError no longer exists
- self.assertTrue(issubclass(self.driver.Warning,Exception))
- self.assertTrue(issubclass(self.driver.Error,Exception))
- else:
- self.failUnless(issubclass(self.driver.Warning,StandardError))
- self.failUnless(issubclass(self.driver.Error,StandardError))
-
- _failUnless(self,
- issubclass(self.driver.InterfaceError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.DatabaseError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.OperationalError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.IntegrityError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.InternalError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.ProgrammingError,self.driver.Error)
- )
- _failUnless(self,
- issubclass(self.driver.NotSupportedError,self.driver.Error)
- )
-
- def test_ExceptionsAsConnectionAttributes(self):
- # OPTIONAL EXTENSION
- # Test for the optional DB API 2.0 extension, where the exceptions
- # are exposed as attributes on the Connection object
- # I figure this optional extension will be implemented by any
- # driver author who is using this test suite, so it is enabled
- # by default.
- con = self._connect()
- drv = self.driver
- _failUnless(self,con.Warning is drv.Warning)
- _failUnless(self,con.Error is drv.Error)
- _failUnless(self,con.InterfaceError is drv.InterfaceError)
- _failUnless(self,con.DatabaseError is drv.DatabaseError)
- _failUnless(self,con.OperationalError is drv.OperationalError)
- _failUnless(self,con.IntegrityError is drv.IntegrityError)
- _failUnless(self,con.InternalError is drv.InternalError)
- _failUnless(self,con.ProgrammingError is drv.ProgrammingError)
- _failUnless(self,con.NotSupportedError is drv.NotSupportedError)
-
-
- def test_commit(self):
- con = self._connect()
- try:
- # Commit must work, even if it doesn't do anything
- con.commit()
- finally:
- con.close()
-
- def test_rollback(self):
- con = self._connect()
- # If rollback is defined, it should either work or throw
- # the documented exception
- if hasattr(con,'rollback'):
- try:
- con.rollback()
- except self.driver.NotSupportedError:
- pass
-
- def test_cursor(self):
- con = self._connect()
- try:
- cur = con.cursor()
- finally:
- con.close()
-
- def test_cursor_isolation(self):
- con = self._connect()
- try:
- # Make sure cursors created from the same connection have
- # the documented transaction isolation level
- cur1 = con.cursor()
- cur2 = con.cursor()
- self.executeDDL1(cur1)
- cur1.execute("%s into %sbooze values ('Victoria Bitter')" % (
- self.insert, self.table_prefix
- ))
- cur2.execute("select name from %sbooze" % self.table_prefix)
- booze = cur2.fetchall()
- self.assertEqual(len(booze),1)
- self.assertEqual(len(booze[0]),1)
- self.assertEqual(booze[0][0],'Victoria Bitter')
- finally:
- con.close()
-
- def test_description(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL1(cur)
- self.assertEqual(cur.description,None,
- 'cursor.description should be none after executing a '
- 'statement that can return no rows (such as DDL)'
- )
- cur.execute('select name from %sbooze' % self.table_prefix)
- self.assertEqual(len(cur.description),1,
- 'cursor.description describes too many columns'
- )
- self.assertEqual(len(cur.description[0]),7,
- 'cursor.description[x] tuples must have 7 elements'
- )
- self.assertEqual(cur.description[0][0].lower(),'name',
- 'cursor.description[x][0] must return column name'
- )
- self.assertEqual(cur.description[0][1],self.driver.STRING,
- 'cursor.description[x][1] must return column type. Got %r'
- % cur.description[0][1]
- )
-
- # Make sure self.description gets reset
- self.executeDDL2(cur)
- self.assertEqual(cur.description,None,
- 'cursor.description not being set to None when executing '
- 'no-result statements (eg. DDL)'
- )
- finally:
- con.close()
-
- def test_rowcount(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL1(cur)
- _failUnless(self,cur.rowcount in (-1,0), # Bug #543885
- 'cursor.rowcount should be -1 or 0 after executing no-result '
- 'statements'
- )
- cur.execute("%s into %sbooze values ('Victoria Bitter')" % (
- self.insert, self.table_prefix
- ))
- _failUnless(self,cur.rowcount in (-1,1),
- 'cursor.rowcount should == number or rows inserted, or '
- 'set to -1 after executing an insert statement'
- )
- cur.execute("select name from %sbooze" % self.table_prefix)
- _failUnless(self,cur.rowcount in (-1,1),
- 'cursor.rowcount should == number of rows returned, or '
- 'set to -1 after executing a select statement'
- )
- self.executeDDL2(cur)
- _failUnless(self,cur.rowcount in (-1,0), # Bug #543885
- 'cursor.rowcount should be -1 or 0 after executing no-result '
- 'statements'
- )
- finally:
- con.close()
-
- lower_func = 'lower'
- def test_callproc(self):
- con = self._connect()
- try:
- cur = con.cursor()
- if self.lower_func and hasattr(cur,'callproc'):
- r = cur.callproc(self.lower_func,('FOO',))
- self.assertEqual(len(r),1)
- self.assertEqual(r[0],'FOO')
- r = cur.fetchall()
- self.assertEqual(len(r),1,'callproc produced no result set')
- self.assertEqual(len(r[0]),1,
- 'callproc produced invalid result set'
- )
- self.assertEqual(r[0][0],'foo',
- 'callproc produced invalid results'
- )
- finally:
- con.close()
-
- def test_close(self):
- con = self._connect()
- try:
- cur = con.cursor()
- finally:
- con.close()
-
- # cursor.execute should raise an Error if called after connection
- # closed
- self.assertRaises(self.driver.Error,self.executeDDL1,cur)
-
- # connection.commit should raise an Error if called after connection'
- # closed.'
- self.assertRaises(self.driver.Error,con.commit)
-
- def test_non_idempotent_close(self):
- con = self._connect()
- con.close()
- # connection.close should raise an Error if called more than once
- #!!! reasonable persons differ about the usefulness of this test and this feature !!!
- self.assertRaises(self.driver.Error,con.close)
-
- def test_execute(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self._paraminsert(cur)
- finally:
- con.close()
-
- def _paraminsert(self,cur):
- self.executeDDL2(cur)
- cur.execute("%s into %sbarflys values ('Victoria Bitter', 'thi%%s :may ca%%(u)se? troub:1e')" % (
- self.insert, self.table_prefix
- ))
- _failUnless(self,cur.rowcount in (-1,1))
-
- if self.driver.paramstyle == 'qmark':
- cur.execute(
- "%s into %sbarflys values (?, 'thi%%s :may ca%%(u)se? troub:1e')" % (self.insert, self.table_prefix),
- ("Cooper's",)
- )
- elif self.driver.paramstyle == 'numeric':
- cur.execute(
- "%s into %sbarflys values (:1, 'thi%%s :may ca%%(u)se? troub:1e')" % (self.insert, self.table_prefix),
- ("Cooper's",)
- )
- elif self.driver.paramstyle == 'named':
- cur.execute(
- "%s into %sbarflys values (:beer, 'thi%%s :may ca%%(u)se? troub:1e')" % (self.insert, self.table_prefix),
- {'beer':"Cooper's"}
- )
- elif self.driver.paramstyle == 'format':
- cur.execute(
- "%s into %sbarflys values (%%s, 'thi%%%%s :may ca%%%%(u)se? troub:1e')" % (self.insert, self.table_prefix),
- ("Cooper's",)
- )
- elif self.driver.paramstyle == 'pyformat':
- cur.execute(
- "%s into %sbarflys values (%%(beer)s, 'thi%%%%s :may ca%%%%(u)se? troub:1e')" % (self.insert, self.table_prefix),
- {'beer':"Cooper's"}
- )
- else:
- self.fail('Invalid paramstyle')
- _failUnless(self,cur.rowcount in (-1,1))
-
- cur.execute('select name, drink from %sbarflys' % self.table_prefix)
- res = cur.fetchall()
- self.assertEqual(len(res),2,'cursor.fetchall returned too few rows')
- beers = [res[0][0],res[1][0]]
- beers.sort()
- self.assertEqual(beers[0],"Cooper's",
- 'cursor.fetchall retrieved incorrect data, or data inserted '
- 'incorrectly'
- )
- self.assertEqual(beers[1],"Victoria Bitter",
- 'cursor.fetchall retrieved incorrect data, or data inserted '
- 'incorrectly'
- )
- trouble = "thi%s :may ca%(u)se? troub:1e"
- self.assertEqual(res[0][1], trouble,
- 'cursor.fetchall retrieved incorrect data, or data inserted '
- 'incorrectly. Got=%s, Expected=%s' % (repr(res[0][1]), repr(trouble)))
- self.assertEqual(res[1][1], trouble,
- 'cursor.fetchall retrieved incorrect data, or data inserted '
- 'incorrectly. Got=%s, Expected=%s' % (repr(res[1][1]), repr(trouble)
- ))
-
- def test_executemany(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL1(cur)
- largs = [ ("Cooper's",) , ("Boag's",) ]
- margs = [ {'beer': "Cooper's"}, {'beer': "Boag's"} ]
- if self.driver.paramstyle == 'qmark':
- cur.executemany(
- '%s into %sbooze values (?)' % (self.insert, self.table_prefix),
- largs
- )
- elif self.driver.paramstyle == 'numeric':
- cur.executemany(
- '%s into %sbooze values (:1)' % (self.insert, self.table_prefix),
- largs
- )
- elif self.driver.paramstyle == 'named':
- cur.executemany(
- '%s into %sbooze values (:beer)' % (self.insert, self.table_prefix),
- margs
- )
- elif self.driver.paramstyle == 'format':
- cur.executemany(
- '%s into %sbooze values (%%s)' % (self.insert, self.table_prefix),
- largs
- )
- elif self.driver.paramstyle == 'pyformat':
- cur.executemany(
- '%s into %sbooze values (%%(beer)s)' % (
- self.insert, self.table_prefix
- ),
- margs
- )
- else:
- self.fail('Unknown paramstyle')
- _failUnless(self,cur.rowcount in (-1,2),
- 'insert using cursor.executemany set cursor.rowcount to '
- 'incorrect value %r' % cur.rowcount
- )
- cur.execute('select name from %sbooze' % self.table_prefix)
- res = cur.fetchall()
- self.assertEqual(len(res),2,
- 'cursor.fetchall retrieved incorrect number of rows'
- )
- beers = [res[0][0],res[1][0]]
- beers.sort()
- self.assertEqual(beers[0],"Boag's",'incorrect data retrieved')
- self.assertEqual(beers[1],"Cooper's",'incorrect data retrieved')
- finally:
- con.close()
-
- def test_fetchone(self):
- con = self._connect()
- try:
- cur = con.cursor()
-
- # cursor.fetchone should raise an Error if called before
- # executing a select-type query
- self.assertRaises(self.driver.Error,cur.fetchone)
-
- # cursor.fetchone should raise an Error if called after
- # executing a query that cannnot return rows
- self.executeDDL1(cur)
- self.assertRaises(self.driver.Error,cur.fetchone)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- self.assertEqual(cur.fetchone(),None,
- 'cursor.fetchone should return None if a query retrieves '
- 'no rows'
- )
- _failUnless(self,cur.rowcount in (-1,0))
-
- # cursor.fetchone should raise an Error if called after
- # executing a query that cannnot return rows
- cur.execute("%s into %sbooze values ('Victoria Bitter')" % (
- self.insert, self.table_prefix
- ))
- self.assertRaises(self.driver.Error,cur.fetchone)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- r = cur.fetchone()
- self.assertEqual(len(r),1,
- 'cursor.fetchone should have retrieved a single row'
- )
- self.assertEqual(r[0],'Victoria Bitter',
- 'cursor.fetchone retrieved incorrect data'
- )
- self.assertEqual(cur.fetchone(),None,
- 'cursor.fetchone should return None if no more rows available'
- )
- _failUnless(self,cur.rowcount in (-1,1))
- finally:
- con.close()
-
- samples = [
- 'Carlton Cold',
- 'Carlton Draft',
- 'Mountain Goat',
- 'Redback',
- 'Victoria Bitter',
- 'XXXX'
- ]
-
- def _populate(self):
- ''' Return a list of sql commands to setup the DB for the fetch
- tests.
- '''
- populate = [
- "%s into %sbooze values ('%s')" % (self.insert, self.table_prefix, s)
- for s in self.samples
- ]
- return populate
-
- def test_fetchmany(self):
- con = self._connect()
- try:
- cur = con.cursor()
-
- # cursor.fetchmany should raise an Error if called without
- #issuing a query
- self.assertRaises(self.driver.Error,cur.fetchmany,4)
-
- self.executeDDL1(cur)
- for sql in self._populate():
- cur.execute(sql)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- r = cur.fetchmany()
- self.assertEqual(len(r),1,
- 'cursor.fetchmany retrieved incorrect number of rows, '
- 'default of arraysize is one.'
- )
- cur.arraysize=10
- r = cur.fetchmany(3) # Should get 3 rows
- self.assertEqual(len(r),3,
- 'cursor.fetchmany retrieved incorrect number of rows'
- )
- r = cur.fetchmany(4) # Should get 2 more
- self.assertEqual(len(r),2,
- 'cursor.fetchmany retrieved incorrect number of rows'
- )
- r = cur.fetchmany(4) # Should be an empty sequence
- self.assertEqual(len(r),0,
- 'cursor.fetchmany should return an empty sequence after '
- 'results are exhausted'
- )
- _failUnless(self,cur.rowcount in (-1,6))
-
- # Same as above, using cursor.arraysize
- cur.arraysize=4
- cur.execute('select name from %sbooze' % self.table_prefix)
- r = cur.fetchmany() # Should get 4 rows
- self.assertEqual(len(r),4,
- 'cursor.arraysize not being honoured by fetchmany'
- )
- r = cur.fetchmany() # Should get 2 more
- self.assertEqual(len(r),2)
- r = cur.fetchmany() # Should be an empty sequence
- self.assertEqual(len(r),0)
- _failUnless(self,cur.rowcount in (-1,6))
-
- cur.arraysize=6
- cur.execute('select name from %sbooze' % self.table_prefix)
- rows = cur.fetchmany() # Should get all rows
- _failUnless(self,cur.rowcount in (-1,6))
- self.assertEqual(len(rows),6)
- self.assertEqual(len(rows),6)
- rows = [r[0] for r in rows]
- rows.sort()
-
- # Make sure we get the right data back out
- for i in range(0,6):
- self.assertEqual(rows[i],self.samples[i],
- 'incorrect data retrieved by cursor.fetchmany'
- )
-
- rows = cur.fetchmany() # Should return an empty list
- self.assertEqual(len(rows),0,
- 'cursor.fetchmany should return an empty sequence if '
- 'called after the whole result set has been fetched'
- )
- _failUnless(self,cur.rowcount in (-1,6))
-
- self.executeDDL2(cur)
- cur.execute('select name from %sbarflys' % self.table_prefix)
- r = cur.fetchmany() # Should get empty sequence
- self.assertEqual(len(r),0,
- 'cursor.fetchmany should return an empty sequence if '
- 'query retrieved no rows'
- )
- _failUnless(self,cur.rowcount in (-1,0))
-
- finally:
- con.close()
-
- def test_fetchall(self):
- con = self._connect()
- try:
- cur = con.cursor()
- # cursor.fetchall should raise an Error if called
- # without executing a query that may return rows (such
- # as a select)
- self.assertRaises(self.driver.Error, cur.fetchall)
-
- self.executeDDL1(cur)
- for sql in self._populate():
- cur.execute(sql)
-
- # cursor.fetchall should raise an Error if called
- # after executing a a statement that cannot return rows
- self.assertRaises(self.driver.Error,cur.fetchall)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- rows = cur.fetchall()
- _failUnless(self,cur.rowcount in (-1,len(self.samples)))
- self.assertEqual(len(rows),len(self.samples),
- 'cursor.fetchall did not retrieve all rows'
- )
- rows = [r[0] for r in rows]
- rows.sort()
- for i in range(0,len(self.samples)):
- self.assertEqual(rows[i],self.samples[i],
- 'cursor.fetchall retrieved incorrect rows'
- )
- rows = cur.fetchall()
- self.assertEqual(
- len(rows),0,
- 'cursor.fetchall should return an empty list if called '
- 'after the whole result set has been fetched'
- )
- _failUnless(self,cur.rowcount in (-1,len(self.samples)))
-
- self.executeDDL2(cur)
- cur.execute('select name from %sbarflys' % self.table_prefix)
- rows = cur.fetchall()
- _failUnless(self,cur.rowcount in (-1,0))
- self.assertEqual(len(rows),0,
- 'cursor.fetchall should return an empty list if '
- 'a select query returns no rows'
- )
-
- finally:
- con.close()
-
- def test_mixedfetch(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL1(cur)
- for sql in self._populate():
- cur.execute(sql)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- rows1 = cur.fetchone()
- rows23 = cur.fetchmany(2)
- rows4 = cur.fetchone()
- rows56 = cur.fetchall()
- _failUnless(self,cur.rowcount in (-1,6))
- self.assertEqual(len(rows23),2,
- 'fetchmany returned incorrect number of rows'
- )
- self.assertEqual(len(rows56),2,
- 'fetchall returned incorrect number of rows'
- )
-
- rows = [rows1[0]]
- rows.extend([rows23[0][0],rows23[1][0]])
- rows.append(rows4[0])
- rows.extend([rows56[0][0],rows56[1][0]])
- rows.sort()
- for i in range(0,len(self.samples)):
- self.assertEqual(rows[i],self.samples[i],
- 'incorrect data retrieved or inserted'
- )
- finally:
- con.close()
-
- def help_nextset_setUp(self,cur):
- ''' Should create a procedure called deleteme
- that returns two result sets, first the
- number of rows in booze then "name from booze"
- '''
- raise NotImplementedError('Helper not implemented')
- #sql="""
- # create procedure deleteme as
- # begin
- # select count(*) from booze
- # select name from booze
- # end
- #"""
- #cur.execute(sql)
-
- def help_nextset_tearDown(self,cur):
- 'If cleaning up is needed after nextSetTest'
- raise NotImplementedError('Helper not implemented')
- #cur.execute("drop procedure deleteme")
-
- def test_nextset(self):
- con = self._connect()
- try:
- cur = con.cursor()
- if not hasattr(cur,'nextset'):
- return
-
- try:
- self.executeDDL1(cur)
- sql=self._populate()
- for sql in self._populate():
- cur.execute(sql)
-
- self.help_nextset_setUp(cur)
-
- cur.callproc('deleteme')
- numberofrows=cur.fetchone()
- assert numberofrows[0]== len(self.samples)
- assert cur.nextset()
- names=cur.fetchall()
- assert len(names) == len(self.samples)
- s=cur.nextset()
- assert s == None,'No more return sets, should return None'
- finally:
- self.help_nextset_tearDown(cur)
-
- finally:
- con.close()
-
- def test_nextset(self):
- raise NotImplementedError('Drivers need to override this test')
-
- def test_arraysize(self):
- # Not much here - rest of the tests for this are in test_fetchmany
- con = self._connect()
- try:
- cur = con.cursor()
- _failUnless(self,hasattr(cur,'arraysize'),
- 'cursor.arraysize must be defined'
- )
- finally:
- con.close()
-
- def test_setinputsizes(self):
- con = self._connect()
- try:
- cur = con.cursor()
- cur.setinputsizes( (25,) )
- self._paraminsert(cur) # Make sure cursor still works
- finally:
- con.close()
-
- def test_setoutputsize_basic(self):
- # Basic test is to make sure setoutputsize doesn't blow up
- con = self._connect()
- try:
- cur = con.cursor()
- cur.setoutputsize(1000)
- cur.setoutputsize(2000,0)
- self._paraminsert(cur) # Make sure the cursor still works
- finally:
- con.close()
-
- def test_setoutputsize(self):
- # Real test for setoutputsize is driver dependant
- raise NotImplementedError('Driver needed to override this test')
-
- def test_None(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL1(cur)
- cur.execute("%s into %sbarflys values ('a', NULL)" % (self.insert, self.table_prefix))
- cur.execute('select drink from %sbarflys' % self.table_prefix)
- r = cur.fetchall()
- self.assertEqual(len(r),1)
- self.assertEqual(len(r[0]),1)
- self.assertEqual(r[0][0],None,'NULL value not returned as None')
- finally:
- con.close()
-
- def test_Date(self):
- d1 = self.driver.Date(2002,12,25)
- d2 = self.driver.DateFromTicks(time.mktime((2002,12,25,0,0,0,0,0,0)))
- # Can we assume this? API doesn't specify, but it seems implied
- # self.assertEqual(str(d1),str(d2))
-
- def test_Time(self):
- t1 = self.driver.Time(13,45,30)
- t2 = self.driver.TimeFromTicks(time.mktime((2001,1,1,13,45,30,0,0,0)))
- # Can we assume this? API doesn't specify, but it seems implied
- # self.assertEqual(str(t1),str(t2))
-
- def test_Timestamp(self):
- t1 = self.driver.Timestamp(2002,12,25,13,45,30)
- t2 = self.driver.TimestampFromTicks(
- time.mktime((2002,12,25,13,45,30,0,0,0))
- )
- # Can we assume this? API doesn't specify, but it seems implied
- # self.assertEqual(str(t1),str(t2))
-
- def test_Binary(self):
- b = self.driver.Binary(str2bytes('Something'))
- b = self.driver.Binary(str2bytes(''))
-
- def test_STRING(self):
- _failUnless(self, hasattr(self.driver,'STRING'),
- 'module.STRING must be defined'
- )
-
- def test_BINARY(self):
- _failUnless(self, hasattr(self.driver,'BINARY'),
- 'module.BINARY must be defined.'
- )
-
- def test_NUMBER(self):
- _failUnless(self, hasattr(self.driver,'NUMBER'),
- 'module.NUMBER must be defined.'
- )
-
- def test_DATETIME(self):
- _failUnless(self, hasattr(self.driver,'DATETIME'),
- 'module.DATETIME must be defined.'
- )
-
- def test_ROWID(self):
- _failUnless(self, hasattr(self.driver,'ROWID'),
- 'module.ROWID must be defined.'
- )
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_avatica.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_avatica.py b/python/phoenixdb/tests/test_avatica.py
deleted file mode 100644
index 6152814..0000000
--- a/python/phoenixdb/tests/test_avatica.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-from phoenixdb.avatica.client import parse_url, urlparse
-
-
-class ParseUrlTest(unittest.TestCase):
-
- def test_parse_url(self):
- self.assertEqual(urlparse.urlparse('http://localhost:8765/'), parse_url('localhost'))
- self.assertEqual(urlparse.urlparse('http://localhost:2222/'), parse_url('localhost:2222'))
- self.assertEqual(urlparse.urlparse('http://localhost:2222/'), parse_url('http://localhost:2222/'))
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_connection.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_connection.py b/python/phoenixdb/tests/test_connection.py
deleted file mode 100644
index 2deacf5..0000000
--- a/python/phoenixdb/tests/test_connection.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-import phoenixdb
-from phoenixdb.tests import TEST_DB_URL
-
-
-@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
-class PhoenixConnectionTest(unittest.TestCase):
-
- def _connect(self, connect_kw_args):
- try:
- r = phoenixdb.connect(TEST_DB_URL, **connect_kw_args)
- except AttributeError:
- self.fail("Failed to connect")
- return r
-
- def test_connection_credentials(self):
- connect_kw_args = {'user': 'SCOTT', 'password': 'TIGER', 'readonly': 'True'}
- con = self._connect(connect_kw_args)
- try:
- self.assertEqual(
- con._connection_args, {'user': 'SCOTT', 'password': 'TIGER'},
- 'Should have extract user and password')
- self.assertEqual(
- con._filtered_args, {'readonly': 'True'},
- 'Should have not extracted foo')
- finally:
- con.close()
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_db.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_db.py b/python/phoenixdb/tests/test_db.py
deleted file mode 100644
index 2fb1a2a..0000000
--- a/python/phoenixdb/tests/test_db.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-import phoenixdb
-import phoenixdb.cursor
-from phoenixdb.errors import InternalError
-from phoenixdb.tests import TEST_DB_URL
-
-
-@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
-class PhoenixDatabaseTest(unittest.TestCase):
-
- def test_select_literal(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- self.addCleanup(db.close)
-
- with db.cursor() as cursor:
- cursor.execute("DROP TABLE IF EXISTS test")
- cursor.execute("CREATE TABLE test (id INTEGER PRIMARY KEY, text VARCHAR)")
- cursor.executemany("UPSERT INTO test VALUES (?, ?)", [[i, 'text {}'.format(i)] for i in range(10)])
-
- with db.cursor() as cursor:
- cursor.itersize = 4
- cursor.execute("SELECT * FROM test WHERE id>1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[i, 'text {}'.format(i)] for i in range(2, 10)])
-
- def test_select_parameter(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- self.addCleanup(db.close)
-
- with db.cursor() as cursor:
- cursor.execute("DROP TABLE IF EXISTS test")
- cursor.execute("CREATE TABLE test (id INTEGER PRIMARY KEY, text VARCHAR)")
- cursor.executemany("UPSERT INTO test VALUES (?, ?)", [[i, 'text {}'.format(i)] for i in range(10)])
-
- with db.cursor() as cursor:
- cursor.itersize = 4
- cursor.execute("SELECT * FROM test WHERE id>? ORDER BY id", [1])
- self.assertEqual(cursor.fetchall(), [[i, 'text {}'.format(i)] for i in range(2, 10)])
-
- def _check_dict_cursor(self, cursor):
- cursor.execute("DROP TABLE IF EXISTS test")
- cursor.execute("CREATE TABLE test (id INTEGER PRIMARY KEY, text VARCHAR)")
- cursor.execute("UPSERT INTO test VALUES (?, ?)", [1, 'text 1'])
- cursor.execute("SELECT * FROM test ORDER BY id")
- self.assertEqual(cursor.fetchall(), [{'ID': 1, 'TEXT': 'text 1'}])
-
- def test_dict_cursor_default_parameter(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True, cursor_factory=phoenixdb.cursor.DictCursor)
- self.addCleanup(db.close)
-
- with db.cursor() as cursor:
- self._check_dict_cursor(cursor)
-
- def test_dict_cursor_default_attribute(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- db.cursor_factory = phoenixdb.cursor.DictCursor
- self.addCleanup(db.close)
-
- with db.cursor() as cursor:
- self._check_dict_cursor(cursor)
-
- def test_dict_cursor(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- self.addCleanup(db.close)
-
- with db.cursor(cursor_factory=phoenixdb.cursor.DictCursor) as cursor:
- self._check_dict_cursor(cursor)
-
- def test_schema(self):
- db = phoenixdb.connect(TEST_DB_URL, autocommit=True)
- self.addCleanup(db.close)
-
- with db.cursor() as cursor:
- try:
- cursor.execute("CREATE SCHEMA IF NOT EXISTS test_schema")
- except InternalError as e:
- if "phoenix.schema.isNamespaceMappingEnabled" in e.message:
- self.skipTest(e.message)
- raise
-
- cursor.execute("DROP TABLE IF EXISTS test_schema.test")
- cursor.execute("CREATE TABLE test_schema.test (id INTEGER PRIMARY KEY, text VARCHAR)")
- cursor.execute("UPSERT INTO test_schema.test VALUES (?, ?)", [1, 'text 1'])
- cursor.execute("SELECT * FROM test_schema.test ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, 'text 1']])
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_dbapi20.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_dbapi20.py b/python/phoenixdb/tests/test_dbapi20.py
deleted file mode 100644
index 0e5c2e4..0000000
--- a/python/phoenixdb/tests/test_dbapi20.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-import phoenixdb
-from . import dbapi20
-from phoenixdb.tests import TEST_DB_URL
-
-
-@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
-class PhoenixDatabaseAPI20Test(dbapi20.DatabaseAPI20Test):
- driver = phoenixdb
- connect_args = (TEST_DB_URL, )
-
- ddl1 = 'create table %sbooze (name varchar(20) primary key)' % dbapi20.DatabaseAPI20Test.table_prefix
- ddl2 = 'create table %sbarflys (name varchar(20) primary key, drink varchar(30))' % dbapi20.DatabaseAPI20Test.table_prefix
- insert = 'upsert'
-
- def test_nextset(self):
- pass
-
- def test_setoutputsize(self):
- pass
-
- def _connect(self):
- con = dbapi20.DatabaseAPI20Test._connect(self)
- con.autocommit = True
- return con
-
- def test_None(self):
- con = self._connect()
- try:
- cur = con.cursor()
- self.executeDDL2(cur)
- cur.execute("%s into %sbarflys values ('a', NULL)" % (self.insert, self.table_prefix))
- cur.execute('select drink from %sbarflys' % self.table_prefix)
- r = cur.fetchall()
- self.assertEqual(len(r), 1)
- self.assertEqual(len(r[0]), 1)
- self.assertEqual(r[0][0], None, 'NULL value not returned as None')
- finally:
- con.close()
-
- def test_autocommit(self):
- con = dbapi20.DatabaseAPI20Test._connect(self)
- self.assertFalse(con.autocommit)
- con.autocommit = True
- self.assertTrue(con.autocommit)
- con.autocommit = False
- self.assertFalse(con.autocommit)
- con.close()
-
- def test_readonly(self):
- con = dbapi20.DatabaseAPI20Test._connect(self)
- self.assertFalse(con.readonly)
- con.readonly = True
- self.assertTrue(con.readonly)
- con.readonly = False
- self.assertFalse(con.readonly)
- con.close()
-
- def test_iter(self):
- # https://www.python.org/dev/peps/pep-0249/#iter
- con = self._connect()
- try:
- cur = con.cursor()
- if hasattr(cur, '__iter__'):
- self.assertIs(cur, iter(cur))
- finally:
- con.close()
-
- def test_next(self):
- # https://www.python.org/dev/peps/pep-0249/#next
- con = self._connect()
- try:
- cur = con.cursor()
- if not hasattr(cur, 'next'):
- return
-
- # cursor.next should raise an Error if called before
- # executing a select-type query
- self.assertRaises(self.driver.Error, cur.next)
-
- # cursor.next should raise an Error if called after
- # executing a query that cannnot return rows
- self.executeDDL1(cur)
- self.assertRaises(self.driver.Error, cur.next)
-
- # cursor.next should return None if a query retrieves '
- # no rows
- cur.execute('select name from %sbooze' % self.table_prefix)
- self.assertRaises(StopIteration, cur.next)
- self.failUnless(cur.rowcount in (-1, 0))
-
- # cursor.next should raise an Error if called after
- # executing a query that cannnot return rows
- cur.execute("%s into %sbooze values ('Victoria Bitter')" % (
- self.insert, self.table_prefix
- ))
- self.assertRaises(self.driver.Error, cur.next)
-
- cur.execute('select name from %sbooze' % self.table_prefix)
- r = cur.next()
- self.assertEqual(len(r), 1, 'cursor.next should have retrieved a row with one column')
- self.assertEqual(r[0], 'Victoria Bitter', 'cursor.next retrieved incorrect data')
- # cursor.next should raise StopIteration if no more rows available
- self.assertRaises(StopIteration, cur.next)
- self.failUnless(cur.rowcount in (-1, 1))
- finally:
- con.close()
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_errors.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_errors.py b/python/phoenixdb/tests/test_errors.py
deleted file mode 100644
index 191ccb1..0000000
--- a/python/phoenixdb/tests/test_errors.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from phoenixdb.tests import DatabaseTestCase
-
-
-class ProgrammingErrorTest(DatabaseTestCase):
-
- def test_invalid_sql(self):
- with self.conn.cursor() as cursor:
- with self.assertRaises(self.conn.ProgrammingError) as cm:
- cursor.execute("UPS")
- self.assertEqual("Syntax error. Encountered \"UPS\" at line 1, column 1.", cm.exception.message)
- self.assertEqual(601, cm.exception.code)
- self.assertEqual("42P00", cm.exception.sqlstate)
-
-
-class IntegrityErrorTest(DatabaseTestCase):
-
- def test_null_in_pk(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key")
- with self.conn.cursor() as cursor:
- with self.assertRaises(self.conn.IntegrityError) as cm:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (NULL)")
- self.assertEqual("Constraint violation. PHOENIXDB_TEST_TBL1.ID may not be null", cm.exception.message)
- self.assertEqual(218, cm.exception.code)
- self.assertIn(cm.exception.sqlstate, ("22018", "23018"))
-
-
-class DataErrorTest(DatabaseTestCase):
-
- def test_number_outside_of_range(self):
- self.createTable("phoenixdb_test_tbl1", "id tinyint primary key")
- with self.conn.cursor() as cursor:
- with self.assertRaises(self.conn.DataError) as cm:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (10000)")
- self.assertEqual("Type mismatch. TINYINT and INTEGER for 10000", cm.exception.message)
- self.assertEqual(203, cm.exception.code)
- self.assertEqual("22005", cm.exception.sqlstate)
-
- def test_division_by_zero(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key")
- with self.conn.cursor() as cursor:
- with self.assertRaises(self.conn.DataError) as cm:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2/0)")
- self.assertEqual("Divide by zero.", cm.exception.message)
- self.assertEqual(202, cm.exception.code)
- self.assertEqual("22012", cm.exception.sqlstate)
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tests/test_types.py
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tests/test_types.py b/python/phoenixdb/tests/test_types.py
deleted file mode 100644
index 2cef0f2..0000000
--- a/python/phoenixdb/tests/test_types.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import unittest
-import datetime
-import phoenixdb
-from decimal import Decimal
-from phoenixdb.tests import DatabaseTestCase
-
-
-class TypesTest(DatabaseTestCase):
-
- def checkIntType(self, type_name, min_value, max_value):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val {}".format(type_name))
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 1)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [1])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [None])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [min_value])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [max_value])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.description[1].type_code, phoenixdb.NUMBER)
- self.assertEqual(cursor.fetchall(), [[1, 1], [2, None], [3, 1], [4, None], [5, min_value], [6, max_value]])
-
- self.assertRaises(
- self.conn.DatabaseError, cursor.execute,
- "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(min_value - 1))
-
- self.assertRaises(
- self.conn.DatabaseError, cursor.execute,
- "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(max_value + 1))
-
- # XXX The server silently truncates the values
-# self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [min_value - 1])
-# self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [max_value + 1])
-
- def test_integer(self):
- self.checkIntType("integer", -2147483648, 2147483647)
-
- def test_unsigned_int(self):
- self.checkIntType("unsigned_int", 0, 2147483647)
-
- def test_bigint(self):
- self.checkIntType("bigint", -9223372036854775808, 9223372036854775807)
-
- def test_unsigned_long(self):
- self.checkIntType("unsigned_long", 0, 9223372036854775807)
-
- def test_tinyint(self):
- self.checkIntType("tinyint", -128, 127)
-
- def test_unsigned_tinyint(self):
- self.checkIntType("unsigned_tinyint", 0, 127)
-
- def test_smallint(self):
- self.checkIntType("smallint", -32768, 32767)
-
- def test_unsigned_smallint(self):
- self.checkIntType("unsigned_smallint", 0, 32767)
-
- def checkFloatType(self, type_name, min_value, max_value):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val {}".format(type_name))
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 1)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [1])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [None])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [min_value])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [max_value])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.description[1].type_code, phoenixdb.NUMBER)
- rows = cursor.fetchall()
- self.assertEqual([r[0] for r in rows], [1, 2, 3, 4, 5, 6])
- self.assertEqual(rows[0][1], 1.0)
- self.assertEqual(rows[1][1], None)
- self.assertEqual(rows[2][1], 1.0)
- self.assertEqual(rows[3][1], None)
- self.assertAlmostEqual(rows[4][1], min_value)
- self.assertAlmostEqual(rows[5][1], max_value)
-
- def test_float(self):
- self.checkFloatType("float", -3.4028234663852886e+38, 3.4028234663852886e+38)
-
- def test_unsigned_float(self):
- self.checkFloatType("unsigned_float", 0, 3.4028234663852886e+38)
-
- def test_double(self):
- self.checkFloatType("double", -1.7976931348623158E+308, 1.7976931348623158E+308)
-
- def test_unsigned_double(self):
- self.checkFloatType("unsigned_double", 0, 1.7976931348623158E+308)
-
- def test_decimal(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val decimal(8,3)")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 33333.333)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [33333.333])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [Decimal('33333.333')])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [None])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.description[1].type_code, phoenixdb.NUMBER)
- rows = cursor.fetchall()
- self.assertEqual([r[0] for r in rows], [1, 2, 3, 4, 5])
- self.assertEqual(rows[0][1], Decimal('33333.333'))
- self.assertEqual(rows[1][1], None)
- self.assertEqual(rows[2][1], Decimal('33333.333'))
- self.assertEqual(rows[3][1], Decimal('33333.333'))
- self.assertEqual(rows[4][1], None)
- self.assertRaises(
- self.conn.DatabaseError, cursor.execute,
- "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [Decimal('1234567890')])
- self.assertRaises(
- self.conn.DatabaseError, cursor.execute,
- "UPSERT INTO phoenixdb_test_tbl1 VALUES (101, ?)", [Decimal('123456.789')])
-
- def test_boolean(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val boolean")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, TRUE)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, FALSE)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [True])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [False])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [None])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.description[1].type_code, phoenixdb.BOOLEAN)
- self.assertEqual(cursor.fetchall(), [[1, True], [2, False], [3, None], [4, True], [5, False], [6, None]])
-
- def test_time(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val time")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '1970-01-01 12:01:02')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [phoenixdb.Time(12, 1, 2)])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [datetime.time(12, 1, 2)])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [None])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.time(12, 1, 2)],
- [2, None],
- [3, datetime.time(12, 1, 2)],
- [4, datetime.time(12, 1, 2)],
- [5, None],
- ])
-
- @unittest.skip("https://issues.apache.org/jira/browse/CALCITE-797")
- def test_time_full(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val time")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '2015-07-12 13:01:02.123')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- [2, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- ])
-
- def test_date(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val date")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '2015-07-12 00:00:00')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [phoenixdb.Date(2015, 7, 12)])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [datetime.date(2015, 7, 12)])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.date(2015, 7, 12)],
- [3, datetime.date(2015, 7, 12)],
- [4, datetime.date(2015, 7, 12)],
- ])
-
- @unittest.skip("https://issues.apache.org/jira/browse/CALCITE-798")
- def test_date_full(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val date")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '2015-07-12 13:01:02.123')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- [2, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- ])
-
- def test_date_null(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val date")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [None])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id") # raises NullPointerException on the server
- self.assertEqual(cursor.fetchall(), [
- [1, None],
- [2, None],
- ])
-
- def test_timestamp(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val timestamp")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '2015-07-12 13:01:02.123')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", [phoenixdb.Timestamp(2015, 7, 12, 13, 1, 2)])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, ?)", [None])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- [2, None],
- [3, datetime.datetime(2015, 7, 12, 13, 1, 2)],
- [4, datetime.datetime(2015, 7, 12, 13, 1, 2, 123000)],
- [5, None],
- ])
-
- @unittest.skip("https://issues.apache.org/jira/browse/CALCITE-796")
- def test_timestamp_full(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val timestamp")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, '2015-07-12 13:01:02.123456789')")
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, datetime.datetime(2015, 7, 12, 13, 1, 2, 123456789)],
- ])
-
- def test_varchar(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val varchar")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 'abc')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", ['abc'])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [None])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, '')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [''])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, 'abc'], [2, None], [3, 'abc'], [4, None], [5, None], [6, None]])
-
- def test_varchar_very_long(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val varchar")
- with self.conn.cursor() as cursor:
- value = '1234567890' * 1000
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ?)", [value])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, value]])
-
- def test_varchar_limited(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val varchar(2)")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 'ab')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, ?)", ['ab'])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [None])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, '')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [''])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, 'ab'], [2, None], [3, 'ab'], [4, None], [5, None], [6, None]])
- self.assertRaises(self.conn.DataError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, 'abc')")
-
- def test_char_null(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val char(2)")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, NULL)")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [None])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (5, '')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (6, ?)", [''])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[2, None], [4, None], [5, None], [6, None]])
- self.assertRaises(self.conn.DataError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, 'abc')")
-
- def test_char(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val char(2)")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 'ab')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", ['ab'])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, 'a')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", ['b'])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, 'ab'], [2, 'ab'], [3, 'a'], [4, 'b']])
- self.assertRaises(self.conn.DataError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, 'abc')")
-
- def test_binary(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val binary(2)")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 'ab')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [phoenixdb.Binary(b'ab')])
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, '\x01\x00')")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [phoenixdb.Binary(b'\x01\x00')])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, b'ab'],
- [2, b'ab'],
- [3, b'\x01\x00'],
- [4, b'\x01\x00'],
- ])
-
- def test_binary_all_bytes(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val binary(256)")
- with self.conn.cursor() as cursor:
- if sys.version_info[0] < 3:
- value = ''.join(map(chr, range(256)))
- else:
- value = bytes(range(256))
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ?)", [phoenixdb.Binary(value)])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [[1, value]])
-
- @unittest.skip("https://issues.apache.org/jira/browse/CALCITE-1050 https://issues.apache.org/jira/browse/PHOENIX-2585")
- def test_array(self):
- self.createTable("phoenixdb_test_tbl1", "id integer primary key, val integer[]")
- with self.conn.cursor() as cursor:
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ARRAY[1, 2])")
- cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [[2, 3]])
- cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
- self.assertEqual(cursor.fetchall(), [
- [1, [1, 2]],
- [2, [2, 3]],
- ])
http://git-wip-us.apache.org/repos/asf/phoenix/blob/e62be9c8/python/phoenixdb/tox.ini
----------------------------------------------------------------------
diff --git a/python/phoenixdb/tox.ini b/python/phoenixdb/tox.ini
new file mode 100644
index 0000000..908696a
--- /dev/null
+++ b/python/phoenixdb/tox.ini
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+[tox]
+envlist = py27,py35,py36
+
+[testenv]
+passenv = PHOENIXDB_TEST_DB_URL
+commands =
+ flake8
+ nosetests -v
+deps = -rrequirements.txt