Commit 501e2ff5 authored by Mark Heppner's avatar Mark Heppner

Minor fixes to pass tests

parent 138b928b
......@@ -304,7 +304,7 @@ class AvaticaClient(object):
response_data = self._apply(request)
response = responses_pb2.ConnectionSyncResponse()
response.ParseFromString(response_data)
return response
return response.conn_props
def openConnection(self, connectionId, info=None):
"""Opens a new connection.
......@@ -452,7 +452,8 @@ class AvaticaClient(object):
request = requests_pb2.ExecuteRequest()
request.statementHandle.id = statementId
request.statementHandle.connection_id = connectionId
request.parameter_values.extend(parameterValues)
if parameterValues is not None:
request.parameter_values.extend(parameterValues)
request.has_parameter_values = parameterValues is not None
request.statementHandle.signature.CopyFrom(signature)
# TODO extra param in 1.8?
......
......@@ -116,10 +116,10 @@ class Connection(object):
if readonly is not None:
props['readOnly'] = bool(readonly)
props = self._client.connectionSync(self._id, props)
self._autocommit = props.conn_props.auto_commit
self._readonly = props.conn_props.read_only
self._autocommit = props.auto_commit
self._readonly = props.read_only
# TODO this is added
self._transactionisolation = props.conn_props.transaction_isolation
self._transactionisolation = props.transaction_isolation
@property
def autocommit(self):
......@@ -131,7 +131,7 @@ class Connection(object):
if self._closed:
raise ProgrammingError('the connection is already closed')
props = self._client.connectionSync(self._id, {'autoCommit': bool(value)})
self._autocommit = props['autoCommit']
self._autocommit = props.auto_commit
@property
def readonly(self):
......@@ -143,7 +143,7 @@ class Connection(object):
if self._closed:
raise ProgrammingError('the connection is already closed')
props = self._client.connectionSync(self._id, {'readOnly': bool(value)})
self._readonly = props['readOnly']
self._readonly = props.read_only
# TODO add properties?
# @property
......
......@@ -22,6 +22,9 @@ __all__ = ['Cursor', 'ColumnDescription']
logger = logging.getLogger(__name__)
# TODO see note in Cursor.rowcount()
MAX_INT = 2 ** 64 - 1
ColumnDescription = collections.namedtuple('ColumnDescription', 'name type_code display_size internal_size precision scale null_ok')
"""Named tuple for representing results from :attr:`Cursor.description`."""
......@@ -102,7 +105,7 @@ class Cursor(object):
@property
def description(self):
if self._signature is None:
if self._signature is None or self._signature.SerializeToString() == '':
return None
description = []
for column in self._signature.columns:
......@@ -141,12 +144,11 @@ class Cursor(object):
self._frame = frame
self._pos = None
if frame is not None:
if frame is not None and frame.SerializeToString() != '':
if frame.rows:
self._pos = 0
# TODO although 'rows' is empty, 'done' seems to always be False...why?
#elif not frame.done:
# raise InternalError('got an empty frame, but the statement is not done yet')
elif not frame.done:
raise InternalError('got an empty frame, but the statement is not done yet')
def _fetch_next_frame(self):
offset = self._frame.offset + len(self._frame.rows)
......@@ -214,11 +216,11 @@ class Cursor(object):
self._set_frame(None)
statement = self._connection._client.prepare(self._connection._id,
operation, maxRowCount=0)
self._set_id(statement['id'])
self._set_signature(statement['signature'])
self._set_id(statement.id)
self._set_signature(statement.signature)
for parameters in seq_of_parameters:
self._connection._client.execute(self._connection._id, self._id,
self._transform_parameters(parameters),
statement.signature, self._transform_parameters(parameters),
maxRowCount=0)
def _transform_row(self, row):
......@@ -305,7 +307,9 @@ class Cursor(object):
the last executed DML statement or -1 if the number cannot be
determined. Note that this will always be set to -1 for select
queries."""
# TODO instead of -1, this ends up being set to unsigned max_long
# TODO instead of -1, this ends up being set to Integer.MAX_VALUE
if self._updatecount == MAX_INT:
return -1
return self._updatecount
@property
......
......@@ -3,7 +3,6 @@ import datetime
import phoenixdb
from decimal import Decimal
from phoenixdb.tests import DatabaseTestCase
from phoenixdb.avatica import AVATICA_1_2_0, AVATICA_1_3_0, AVATICA_1_4_0
class TypesTest(DatabaseTestCase):
......@@ -20,12 +19,12 @@ class TypesTest(DatabaseTestCase):
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]])
if self.conn._client.version >= AVATICA_1_4_0:
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])
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)
......@@ -84,8 +83,6 @@ class TypesTest(DatabaseTestCase):
self.checkFloatType("unsigned_double", 0, 1.7976931348623158E+308)
def test_decimal(self):
if self.conn._client.version < AVATICA_1_4_0:
raise unittest.SkipTest('decimal only works correctly with Calcite >= 1.4.0: https://issues.apache.org/jira/browse/CALCITE-795')
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)")
......@@ -224,8 +221,6 @@ class TypesTest(DatabaseTestCase):
self.assertEqual(cursor.fetchall(), [[1, 'abc'], [2, None], [3, 'abc'], [4, None], [5, None], [6, None]])
def test_varchar_very_long(self):
if self.conn._client.version < AVATICA_1_4_0:
raise unittest.SkipTest('long requests only work with Calcite >= 1.4.0: https://issues.apache.org/jira/browse/CALCITE-780')
self.createTable("phoenixdb_test_tbl1", "id integer primary key, val varchar")
with self.conn.cursor() as cursor:
value = '1234567890' * 1000
......@@ -305,4 +300,3 @@ class TypesTest(DatabaseTestCase):
[1, [1,2]],
[2, [2,3]],
])
......@@ -20,7 +20,8 @@ from phoenixdb.calcite import common_pb2
__all__ = [
'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', 'TimestampFromTicks',
'Binary', 'REP_TYPES', 'REP_TYPES_MAP', 'PHOENIX_PARAMETERS', 'PHOENIX_PARAMETERS_MAP',
'Binary', 'STRING', 'BINARY', 'NUMBER', 'DATETIME', 'ROWID', 'BOOLEAN',
'REP_TYPES', 'REP_TYPES_MAP', 'PHOENIX_PARAMETERS', 'PHOENIX_PARAMETERS_MAP',
'TypeHelper',
]
......@@ -95,6 +96,42 @@ def datetime_to_java_sql_timestamp(d):
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 __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
REP_TYPES = {
'bool_value': [
common_pb2.PRIMITIVE_BOOLEAN,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment