@@ -12,8 +12,8 @@ from libcpp cimport bool as c_bool
1212from libcpp.memory cimport shared_ptr
1313from libcpp.string cimport string as c_string
1414from libcpp.vector cimport vector
15- from .errors import (Error, OperationalError)
16- from .errorcode import ER_FAILED_TO_READ_ARROW_STREAM
15+ from .errors import (Error, OperationalError, InterfaceError )
16+ from .errorcode import ( ER_FAILED_TO_READ_ARROW_STREAM, ER_FAILED_TO_CONVERT_ROW_TO_PYTHON_TYPE)
1717
1818logger = getLogger(__name__ )
1919
@@ -27,8 +27,13 @@ ROW_UNIT, TABLE_UNIT, EMPTY_UNIT = 'row', 'table', ''
2727
2828
2929cdef extern from " cpp/ArrowIterator/CArrowIterator.hpp" namespace " sf" :
30+ cdef cppclass ReturnVal:
31+ PyObject * successObj;
32+
33+ PyObject * exception;
34+
3035 cdef cppclass CArrowIterator:
31- PyObject * next();
36+ shared_ptr[ReturnVal] next();
3237
3338
3439cdef extern from " cpp/ArrowIterator/CArrowChunkIterator.hpp" namespace " sf" :
@@ -132,20 +137,21 @@ cdef class PyArrowIterator(EmptyPyArrowIterator):
132137 cdef object context
133138 cdef CArrowIterator* cIterator
134139 cdef str unit
135- cdef PyObject * cret
140+ cdef shared_ptr[ReturnVal] cret
136141 cdef vector[shared_ptr[CRecordBatch]] batches
137142 cdef object use_dict_result
143+ cdef object cursor
138144
139- def __cinit__ (self , object py_inputstream , object arrow_context , object use_dict_result ):
145+ def __cinit__ (self , object cursor , object py_inputstream , object arrow_context , object use_dict_result ):
140146 cdef shared_ptr[InputStream] input_stream
141147 cdef shared_ptr[CRecordBatchReader] reader
142148 cdef shared_ptr[CRecordBatch] record_batch
143149 input_stream.reset(new PyReadableFile(py_inputstream))
144150 cdef CStatus ret = CRecordBatchStreamReader.Open(input_stream.get(), & reader)
145151 if not ret.ok():
146152 Error.errorhandler_wrapper(
147- None ,
148- None ,
153+ cursor.connection ,
154+ cursor ,
149155 OperationalError,
150156 {
151157 u ' msg' : u ' Failed to open arrow stream: ' + ret.message(),
@@ -156,8 +162,8 @@ cdef class PyArrowIterator(EmptyPyArrowIterator):
156162 ret = reader.get().ReadNext(& record_batch)
157163 if not ret.ok():
158164 Error.errorhandler_wrapper(
159- None ,
160- None ,
165+ cursor.connection ,
166+ cursor ,
161167 OperationalError,
162168 {
163169 u ' msg' : u ' Failed to read next arrow batch: ' + ret.message(),
@@ -175,18 +181,24 @@ cdef class PyArrowIterator(EmptyPyArrowIterator):
175181 self .cIterator = NULL
176182 self .unit = ' '
177183 self .use_dict_result = use_dict_result
184+ self .cursor = cursor
178185
179186 def __dealloc__ (self ):
180187 del self .cIterator
181188
182189 def __next__ (self ):
183190 self .cret = self .cIterator.next()
184191
185- if not self .cret:
186- logger.error(" Internal error from CArrowIterator\n " )
192+ if not self .cret.get().successObj:
193+ msg = u ' Failed to convert current row, cause: ' + str (< object > self .cret.get().exception)
194+ Error.errorhandler_wrapper(self .cursor.connection, self .cursor, InterfaceError,
195+ {
196+ u ' msg' : msg,
197+ u ' errno' : ER_FAILED_TO_CONVERT_ROW_TO_PYTHON_TYPE
198+ })
187199 # it looks like this line can help us get into python and detect the global variable immediately
188200 # however, this log will not show up for unclear reason
189- ret = < object > self .cret
201+ ret = < object > self .cret.get().successObj
190202
191203 if ret is None :
192204 raise StopIteration
0 commit comments