66package org .opensearch .sql .opensearch .executor ;
77
88import com .google .common .base .Suppliers ;
9+ import java .lang .reflect .Method ;
910import java .sql .PreparedStatement ;
1011import java .sql .ResultSet ;
1112import java .sql .ResultSetMetaData ;
1213import java .sql .SQLException ;
1314import java .util .ArrayList ;
15+ import java .util .HashMap ;
1416import java .util .LinkedHashMap ;
1517import java .util .List ;
1618import java .util .Map ;
1719import java .util .Optional ;
1820import java .util .concurrent .ConcurrentHashMap ;
1921import java .util .concurrent .atomic .AtomicReference ;
2022import java .util .function .Supplier ;
23+ import org .apache .calcite .avatica .AvaticaResultSet ;
24+ import org .apache .calcite .avatica .util .Cursor ;
2125import org .apache .calcite .plan .RelOptUtil ;
2226import org .apache .calcite .rel .RelNode ;
2327import org .apache .calcite .rel .RelRoot ;
3438import org .apache .calcite .sql .validate .SqlUserDefinedFunction ;
3539import org .apache .logging .log4j .LogManager ;
3640import org .apache .logging .log4j .Logger ;
41+ import org .locationtech .jts .geom .Point ;
3742import org .opensearch .sql .ast .statement .Explain .ExplainFormat ;
3843import org .opensearch .sql .calcite .CalcitePlanContext ;
3944import org .opensearch .sql .calcite .utils .CalciteToolsHelper .OpenSearchRelRunners ;
4247import org .opensearch .sql .common .response .ResponseListener ;
4348import org .opensearch .sql .data .model .ExprTupleValue ;
4449import org .opensearch .sql .data .model .ExprValue ;
50+ import org .opensearch .sql .data .model .ExprValueUtils ;
4551import org .opensearch .sql .data .type .ExprCoreType ;
4652import org .opensearch .sql .data .type .ExprType ;
4753import org .opensearch .sql .executor .ExecutionContext ;
5258import org .opensearch .sql .expression .function .BuiltinFunctionName ;
5359import org .opensearch .sql .expression .function .PPLFuncImpTable ;
5460import org .opensearch .sql .opensearch .client .OpenSearchClient ;
61+ import org .opensearch .sql .opensearch .data .value .OpenSearchExprGeoPointValue ;
5562import org .opensearch .sql .opensearch .executor .protector .ExecutionProtector ;
5663import org .opensearch .sql .opensearch .functions .DistinctCountApproxAggFunction ;
5764import org .opensearch .sql .opensearch .functions .GeoIpFunction ;
58- import org .opensearch .sql .opensearch .util .JdbcOpenSearchDataTypeConvertor ;
5965import org .opensearch .sql .planner .physical .PhysicalPlan ;
6066import org .opensearch .sql .storage .TableScanOperator ;
6167import org .opensearch .transport .client .node .NodeClient ;
@@ -212,6 +218,61 @@ public void execute(
212218 });
213219 }
214220
221+ /**
222+ * Retrieves column accessors from AvaticaResultSet using reflection. This method accesses the
223+ * private getAccessor method to obtain direct access to column data.
224+ *
225+ * @param rs the ResultSet to get accessors from
226+ * @param columnCount the number of columns in the ResultSet
227+ * @return list of Cursor.Accessor objects for each column
228+ * @throws SQLException if reflection fails or column access is invalid
229+ */
230+ private List <Cursor .Accessor > getAccessors (ResultSet rs , int columnCount ) throws SQLException {
231+ List <Cursor .Accessor > accessorList = new ArrayList <>();
232+ try {
233+ Method method = AvaticaResultSet .class .getDeclaredMethod ("getAccessor" , int .class );
234+ method .setAccessible (true );
235+ for (int i = 1 ; i <= columnCount ; i ++) {
236+ accessorList .add ((Cursor .Accessor ) method .invoke (rs , i ));
237+ }
238+ } catch (Exception e ) {
239+ throw new SQLException ("Unable to get accessors" , e );
240+ }
241+ return accessorList ;
242+ }
243+
244+ /**
245+ * Process values recursively, handling geo points and nested maps. Geo points are converted to
246+ * OpenSearchExprGeoPointValue. Maps are recursively processed to handle nested structures.
247+ */
248+ private static Object processValue (Object value ) {
249+ if (value == null ) {
250+ return null ;
251+ }
252+ if (value instanceof Point ) {
253+ Point point = (Point ) value ;
254+ return new OpenSearchExprGeoPointValue (point .getY (), point .getX ());
255+ }
256+ if (value instanceof Map ) {
257+ Map <String , Object > map = (Map <String , Object >) value ;
258+ Map <String , Object > convertedMap = new HashMap <>();
259+ for (Map .Entry <String , Object > entry : map .entrySet ()) {
260+ convertedMap .put (entry .getKey (), processValue (entry .getValue ()));
261+ }
262+ return convertedMap ;
263+ }
264+ if (value instanceof List ) {
265+ List <Object > list = (List <Object >) value ;
266+ List <Object > convertedList = new ArrayList <>();
267+ for (Object item : list ) {
268+ convertedList .add (processValue (item ));
269+ }
270+ return convertedList ;
271+ }
272+ // For other types, return as-is
273+ return value ;
274+ }
275+
215276 private void buildResultSet (
216277 ResultSet resultSet ,
217278 RelDataType rowTypes ,
@@ -221,6 +282,7 @@ private void buildResultSet(
221282 // Get the ResultSet metadata to know about columns
222283 ResultSetMetaData metaData = resultSet .getMetaData ();
223284 int columnCount = metaData .getColumnCount ();
285+ List <Cursor .Accessor > accessorList = getAccessors (resultSet , columnCount );
224286 List <RelDataType > fieldTypes =
225287 rowTypes .getFieldList ().stream ().map (RelDataTypeField ::getType ).toList ();
226288 List <ExprValue > values = new ArrayList <>();
@@ -230,11 +292,9 @@ private void buildResultSet(
230292 // Loop through each column
231293 for (int i = 1 ; i <= columnCount ; i ++) {
232294 String columnName = metaData .getColumnName (i );
233- int sqlType = metaData .getColumnType (i );
234- RelDataType fieldType = fieldTypes .get (i - 1 );
235- ExprValue exprValue =
236- JdbcOpenSearchDataTypeConvertor .getExprValueFromSqlType (
237- resultSet , i , sqlType , fieldType , columnName );
295+ Object value = accessorList .get (i - 1 ).getObject ();
296+ Object converted = processValue (value );
297+ ExprValue exprValue = ExprValueUtils .fromObjectValue (converted );
238298 row .put (columnName , exprValue );
239299 }
240300 values .add (ExprTupleValue .fromExprValueMap (row ));
0 commit comments