phoenix 报错:type org.apache.phoenix.schema.types.PhoenixArray is not supported
今天用phoenix报如下错误:
主要原因:
hbase的表中某字段类型是array,phoenix目前不支持此类型
解决方法:
复制替换phoenix包的cursor文件
- # Copyright 2015 Lukas Lalinsky
- #
- # Licensed 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 logging,re
- import collections
- from phoenixdb.types import TypeHelper
- from phoenixdb.errors import OperationalError, NotSupportedError, ProgrammingError, InternalError
- from phoenixdb.calcite import common_pb2
- __all__ = ['Cursor', 'ColumnDescription', 'DictCursor']
- 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`."""
- class Cursor(object):
- """Database cursor for executing queries and iterating over results.
- You should not construct this object manually, use :meth:`Connection.cursor() <phoenixdb.connection.Connection.cursor>` instead.
- """
- arraysize = 1
- """
- Read/write attribute specifying the number of rows to fetch
- at a time with :meth:`fetchmany`. It defaults to 1 meaning to
- fetch a single row at a time.
- """
- itersize = 2000
- """
- Read/write attribute specifying the number of rows to fetch
- from the backend at each network roundtrip during iteration
- on the cursor. The default is 2000.
- """
- def __init__(self, connection, id=None):
- self._connection = connection
- self._id = id
- self._signature = None
- self._column_data_types = []
- self._frame = None
- self._pos = None
- self._closed = False
- self.arraysize = self.__class__.arraysize
- self.itersize = self.__class__.itersize
- self._updatecount = -1
- def __del__(self):
- if not self._connection._closed and not self._closed:
- self.close()
- def __enter__(self):
- return self
- def __exit__(self, exc_type, exc_value, traceback):
- if not self._closed:
- self.close()
- def __iter__(self):
- return self
- def __next__(self):
- row = self.fetchone()
- if row is None:
- raise StopIteration
- return row
- next = __next__
- def close(self):
- """Closes the cursor.
- No further operations are allowed once the cursor is closed.
- If the cursor is used in a ``with`` statement, this method will
- be automatically called at the end of the ``with`` block.
- """
- if self._closed:
- raise ProgrammingError('the cursor is already closed')
- if self._id is not None:
- self._connection._client.close_statement(self._connection._id, self._id)
- self._id = None
- self._signature = None
- self._column_data_types = []
- self._frame = None
- self._pos = None
- self._closed = True
- @property
- def closed(self):
- """Read-only attribute specifying if the cursor is closed or not."""
- return self._closed
- @property
- def description(self):
- if self._signature is None:
- return None
- description = []
- for column in self._signature.columns:
- description.append(ColumnDescription(
- column.column_name,
- column.type.name,
- column.display_size,
- None,
- column.precision,
- column.scale,
- None if column.nullable == 2 else bool(column.nullable),
- ))
- return description
- def _set_id(self, id):
- if self._id is not None and self._id != id:
- self._connection._client.close_statement(self._connection._id, self._id)
- self._id = id
- def _set_signature(self, signature):
- self._signature = signature
- self._column_data_types = []
- self._parameter_data_types = []
- if signature is None:
- return
- for column in signature.columns:
- dtype = TypeHelper.from_class(column.column_class_name)
- self._column_data_types.append(dtype)
- for parameter in signature.parameters:
- dtype = TypeHelper.from_class(parameter.class_name)
- self._parameter_data_types.append(dtype)
- def _set_frame(self, frame):
- self._frame = frame
- self._pos = None
- if frame is not None:
- if frame.rows:
- self._pos = 0
- 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)
- frame = self._connection._client.fetch(self._connection._id, self._id,
- offset=offset, frame_max_size=self.itersize)
- self._set_frame(frame)
- def _process_results(self, results):
- if results:
- result = results[0]
- if result.own_statement:
- self._set_id(result.statement_id)
- self._set_signature(result.signature if result.HasField('signature') else None)
- self._set_frame(result.first_frame if result.HasField('first_frame') else None)
- self._updatecount = result.update_count
- def _transform_parameters(self, parameters):
- typed_parameters = []
- for value, data_type in zip(parameters, self._parameter_data_types):
- field_name, rep, mutate_to, cast_from = data_type
- typed_value = common_pb2.TypedValue()
- if value is None:
- typed_value.null = True
- typed_value.type = common_pb2.NULL
- else:
- typed_value.null = False
- # use the mutator function
- if mutate_to is not None:
- value = mutate_to(value)
- typed_value.type = rep
- setattr(typed_value, field_name, value)
- typed_parameters.append(typed_value)
- return typed_parameters
- def execute(self, operation, parameters=None):
- if self._closed:
- raise ProgrammingError('the cursor is already closed')
- self._updatecount = -1
- self._set_frame(None)
- if parameters is None:
- if self._id is None:
- self._set_id(self._connection._client.create_statement(self._connection._id))
- results = self._connection._client.prepare_and_execute(self._connection._id, self._id,
- operation, first_frame_max_size=self.itersize)
- self._process_results(results)
- else:
- statement = self._connection._client.prepare(self._connection._id,
- operation)
- self._set_id(statement.id)
- self._set_signature(statement.signature)
- results = self._connection._client.execute(self._connection._id, self._id,
- statement.signature, self._transform_parameters(parameters),
- first_frame_max_size=self.itersize)
- self._process_results(results)
- def executemany(self, operation, seq_of_parameters):
- if self._closed:
- raise ProgrammingError('the cursor is already closed')
- self._updatecount = -1
- self._set_frame(None)
- statement = self._connection._client.prepare(self._connection._id,
- operation, max_rows_total=0)
- 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,
- statement.signature, self._transform_parameters(parameters),
- first_frame_max_size=0)
- def _transform_row(self, row):
- """Transforms a Row into Python values.
- :param row:
- A ``common_pb2.Row`` object.
- :returns:
- A list of values casted into the correct Python types.
- :raises:
- NotImplementedError
- """
- tmp_row = []
- for i, column in enumerate(row.value):
- if column.has_array_value:
- # 修改的地方===============
- column_value = str(column.value)
- if 'INTEGER' in column_value:
- pattern = '(\d+)'
- elif 'string_value' in column_value:
- pattern = 'string_value: "(.+)"'
- else:
- raise NotImplementedError('array types are not supported')
- value = re.findall(pattern, str(column.value))
- tmp_row.append(value)
- # =========================
- elif column.scalar_value.null:
- tmp_row.append(None)
- else:
- field_name, rep, mutate_to, cast_from = self._column_data_types[i]
- # get the value from the field_name
- value = getattr(column.scalar_value, field_name)
- # cast the value
- if cast_from is not None:
- value = cast_from(value)
- tmp_row.append(value)
- return tmp_row
- def fetchone(self):
- if self._frame is None:
- raise ProgrammingError('no select statement was executed')
- if self._pos is None:
- return None
- rows = self._frame.rows
- row = self._transform_row(rows[self._pos])
- self._pos += 1
- if self._pos >= len(rows):
- self._pos = None
- if not self._frame.done:
- self._fetch_next_frame()
- return row
- def fetchmany(self, size=None):
- if size is None:
- size = self.arraysize
- rows = []
- while size > 0:
- row = self.fetchone()
- if row is None:
- break
- rows.append(row)
- size -= 1
- return rows
- def fetchall(self):
- rows = []
- while True:
- row = self.fetchone()
- if row is None:
- break
- rows.append(row)
- return rows
- def setinputsizes(self, sizes):
- pass
- def setoutputsize(self, size, column=None):
- pass
- @property
- def connection(self):
- """Read-only attribute providing access to the :class:`Connection <phoenixdb.connection.Connection>` object this cursor was created from."""
- return self._connection
- @property
- def rowcount(self):
- """Read-only attribute specifying the number of rows affected by
- 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 Integer.MAX_VALUE
- if self._updatecount == MAX_INT:
- return -1
- return self._updatecount
- @property
- def rownumber(self):
- """Read-only attribute providing the current 0-based index of the
- cursor in the result set or ``None`` if the index cannot be
- determined.
- The index can be seen as index of the cursor in a sequence
- (the result set). The next fetch operation will fetch the
- row indexed by :attr:`rownumber` in that sequence.
- """
- if self._frame is not None and self._pos is not None:
- return self._frame.offset + self._pos
- return self._pos
- class DictCursor(Cursor):
- """A cursor which returns results as a dictionary"""
- def _transform_row(self, row):
- row = super(DictCursor, self)._transform_row(row)
- d = {}
- for ind, val in enumerate(row):
- d[self._signature.columns[ind].column_name] = val
- return d
复制替换phoenix包下的types.py文件
- # Copyright 2015 Lukas Lalinsky
- #
- # Licensed 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.calcite import common_pb2
- __all__ = [
- 'Date', 'Time', 'Timestamp', 'DateFromTicks', 'TimeFromTicks', 'TimestampFromTicks',
- 'Binary', 'STRING', 'BINARY', 'NUMBER', 'DATETIME', 'ROWID', 'BOOLEAN',
- 'JAVA_CLASSES', 'JAVA_CLASSES_MAP', 'TypeHelper', 'PhoenixArray'
- ]
- def PhoenixArray(value):
- print(value)
- return value
- 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
- 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),
- ('java.sql.Array', common_pb2.ARRAY, None, None),
- ],
- '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 if sys.version_info[0] < 3 else int),
- ('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 == 'org.apache.phoenix.schema.types.PhoenixArray':
- klass = "java.sql.Array"
- if klass not in JAVA_CLASSES_MAP:
- raise NotImplementedError('type {} is not supported'.format(klass))
- return JAVA_CLASSES_MAP[klass]
改动后只支持 array里面的值是int、string例如 array(1,2,3),array('12','a','b')
phoenix 报错:type org.apache.phoenix.schema.types.PhoenixArray is not supported的更多相关文章
- phoenix启动报错:org.apache.phoenix.exception.PhoenixIOException: SYSTEM.CATALOG
错误: org.apache.phoenix.exception.PhoenixIOException: SYSTEM.CATALOG at org.apache.phoenix.util.Serve ...
- 在DBeaver中phoenix查询报错:org.apache.phoenix.exception.PhoenixIOException: The system cannot find the path specified
环境:Phoenix:4.4,win7系统 问题:Phoenix在查询hbase时,报"系统找不到指定路径". 解决: 请参见 https://distcp.quora.com/C ...
- Eclipse配置tomcat8.5.7报错:The Apache Tomcat installation at this directory is version 8.5.27. A Tomcat 8.0 installation is...
Eclipse配置tomcat8.5.7报错:The Apache Tomcat installation at this directory is version 8.5.27. A Tomcat ...
- 【mybatis】mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 或者 feign被调用方使用的mybatis总报空指针异常java.lang.NullPointerException,而变量都没有问题的情况
mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 需要检查的步骤: ...
- 【mybatis】mybatis方法访问报错:org.apache.ibatis.builder.IncompleteElementException: Could not find result map com.pisen.cloud.luna.ms.goods.base.domain.GoodsConfigQuery
在调用mapper.xml中的方法的时候,报错: org.apache.ibatis.builder.IncompleteElementException: Could not find result ...
- 启动项目报错:org.apache.catalina.LifecycleException: Failed to start component
原因 环境异常重启,项目java进程未关闭,原项目的端口依旧在占用. 一般为8080端口被占用 解决方法 以下两种方法都可以解决,原理相同(结束异常进程) 1. 简单粗暴: 打开任务管理器找到java ...
- TOMCAT启动报错:org.apache.tomcat.jni.Error: 730055
TOMCAT启动报错:org.apache.tomcat.jni.Error: 730055 具体原因:不清楚 解决方式:重启应用服务器后,再启动tomcat就可以了 欢迎关注公众号,学习kettle ...
- 使用IDEA操作Hbase API 报错:org.apache.hadoop.hbase.client.RetriesExhaustedException的解决方法:
使用IDEA操作Hbase API 报错:org.apache.hadoop.hbase.client.RetriesExhaustedException的解决方法: 1.错误详情: Excepti ...
- 通过phoenix创建hbase表失败,创建语句卡住,hbase-hmaster报错:exception=org.apache.hadoop.hbase.TableExistsException: SYNC_BUSINESS_INFO_BYDAY_EFFECT
问题描述: 前几天一个同事来说,通过phoenix创建表失败了,一直报表存在的错误,删除也报错,然后就针对这个问题找下解决方案. 问题分析: 1.通过phoenix创建表,一直卡住不动了.创建语句如下 ...
随机推荐
- pycharm的快捷键
一.编辑(Editing) Ctrl+Space 基本的代码完成(类.方法.属性) Ctrl+Alt+Space 快速导入任意类 Ctrl+Shift+Enter 语句完成 Ctrl+P 参数信息(在 ...
- kickstart文件制作与光盘镜像制作
kickstart文件,是linux(Redhat.Centos.Fedora)下的anaconda安装程序的配置文件,基于此文件,可以实现linux的无人值守安装,在需要大规模部署安装linux的情 ...
- calcOpticalFlowPyrLK
void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg, ...
- JavaScript调用上下文(第九天)
call与apply用法 使用哪个对象去调用相应的方法: var name="window"; var obj={ name:"obj" } function ...
- 微信小程序wx.navigateTo页面不跳转
排查后发现: 若是在全局app.json中配置了tabBar,引用的链接与wx.navigateTo页面跳转url地址相同就无法实现跳转.
- 【缓存】介绍和使用场景 MEMCACHE REDIS
缓存缓存就是在内存中存储的数据备份,当数据没有发生本质改变的时候,我们就不让数据的查询去数据库进行操作,而去内存中取数据,这样就大大降低了数据库的读写次数,而且从内存中读数据的速度比去数据库查询要快一 ...
- softmax 损失函数求导过程
前言:softmax中的求导包含矩阵与向量的求导关系,记录的目的是为了回顾. 下图为利用softmax对样本进行k分类的问题,其损失函数的表达式为结构风险,第二项是模型结构的正则化项. 首先,每个qu ...
- TensorFlow机器学习实战指南之第二章
一.计算图中的操作 在这个例子中,我们将结合前面所学的知识,传入一个列表到计算图中的操作,并打印返回值: 声明张量和占位符.这里,创建一个numpy数组,传入计算图操作: import tensorf ...
- layui 表格组件不能访问连续的属性的解决办法
table.js里第741行改成这样,它这里只能访问一级属性// var content = item1[field]; 不能访问对象内的对象,比如item1.depart.name,只能访问一级属性 ...
- js求两个数组的交集|并集|差集|去重
let a = [1,2,3], b= [2, 4, 5]; 1.差集 (a-b 差集:属于a但不属于b的集合) a-b = [1,3] (b-a 差集:属于b但不属于a的集合) b-a = [4 ...