1919
2020import org .apache .fluss .annotation .PublicEvolving ;
2121import org .apache .fluss .record .ChangeType ;
22- import org .apache .fluss .row .columnar .ColumnarRow ;
23- import org .apache .fluss .row .columnar .VectorizedColumnBatch ;
2422import org .apache .fluss .types .ArrayType ;
2523import org .apache .fluss .types .DataType ;
2624import org .apache .fluss .types .MapType ;
3230import java .util .HashMap ;
3331import java .util .Map ;
3432
35- import static org .apache .fluss .row .InternalArray .createDeepElementGetter ;
3633import static org .apache .fluss .types .DataTypeChecks .getLength ;
3734import static org .apache .fluss .types .DataTypeChecks .getPrecision ;
3835import static org .apache .fluss .types .DataTypeChecks .getScale ;
@@ -239,22 +236,35 @@ static FieldGetter createFieldGetter(DataType fieldType, int fieldPos) {
239236 }
240237
241238 /**
242- * Creates a deep accessor for getting elements in an internal array data structure at the given
243- * position. It returns new objects (GenericArray/GenericMap/GenericMap ) for nested
244- * array/map/row types.
239+ * Creates a deep accessor for getting elements in an internal row data structure at the given
240+ * position. Returns new objects (GenericArray/GenericMap/GenericRow ) for nested array/map/row
241+ * types to prevent use-after-free when the underlying buffer is released .
245242 *
246- * <p>NOTE: Currently, it is only used for deep copying {@link ColumnarRow} for Arrow which
247- * avoid the arrow buffer is released before accessing elements. It doesn't deep copy STRING and
248- * BYTES types, because {@link ColumnarRow} already deep copies the bytes, see {@link
249- * VectorizedColumnBatch#getString(int, int)}. This can be removed once we supports object reuse
250- * for Arrow {@link ColumnarRow}, see {@code CompletedFetch#toScanRecord(LogRecord)}.
243+ * <p>ARROW already deep copies strings in VectorizedColumnBatch, so copyStrings should be
244+ * false. INDEXED and COMPACTED rows reference pooled network buffers, so copyStrings should be
245+ * true to copy STRING/CHAR via BinaryString.copy().
251246 */
252- static FieldGetter createDeepFieldGetter (DataType fieldType , int fieldPos ) {
247+ static FieldGetter createDeepFieldGetter (
248+ DataType fieldType , int fieldPos , boolean copyStrings ) {
253249 final FieldGetter fieldGetter ;
254250 switch (fieldType .getTypeRoot ()) {
251+ case CHAR :
252+ final int charLen = getLength (fieldType );
253+ fieldGetter =
254+ copyStrings
255+ ? row -> row .getChar (fieldPos , charLen ).copy ()
256+ : row -> row .getChar (fieldPos , charLen );
257+ break ;
258+ case STRING :
259+ fieldGetter =
260+ copyStrings
261+ ? row -> row .getString (fieldPos ).copy ()
262+ : row -> row .getString (fieldPos );
263+ break ;
255264 case ARRAY :
256265 DataType elementType = ((ArrayType ) fieldType ).getElementType ();
257- InternalArray .ElementGetter nestedGetter = createDeepElementGetter (elementType );
266+ InternalArray .ElementGetter nestedGetter =
267+ InternalArray .createDeepElementGetter (elementType , copyStrings );
258268 fieldGetter =
259269 row -> {
260270 InternalArray array = row .getArray (fieldPos );
@@ -268,9 +278,9 @@ static FieldGetter createDeepFieldGetter(DataType fieldType, int fieldPos) {
268278 case MAP :
269279 MapType mapType = (MapType ) fieldType ;
270280 InternalArray .ElementGetter keyGetter =
271- createDeepElementGetter (mapType .getKeyType ());
281+ InternalArray . createDeepElementGetter (mapType .getKeyType (), copyStrings );
272282 InternalArray .ElementGetter valueGetter =
273- createDeepElementGetter (mapType .getValueType ());
283+ InternalArray . createDeepElementGetter (mapType .getValueType (), copyStrings );
274284 fieldGetter =
275285 row -> {
276286 InternalMap map = row .getMap (fieldPos );
@@ -288,7 +298,8 @@ static FieldGetter createDeepFieldGetter(DataType fieldType, int fieldPos) {
288298 int numFields = rowType .getFieldCount ();
289299 FieldGetter [] nestedFieldGetters = new FieldGetter [numFields ];
290300 for (int i = 0 ; i < numFields ; i ++) {
291- nestedFieldGetters [i ] = createDeepFieldGetter (rowType .getTypeAt (i ), i );
301+ nestedFieldGetters [i ] =
302+ createDeepFieldGetter (rowType .getTypeAt (i ), i , copyStrings );
292303 }
293304 fieldGetter =
294305 row -> {
0 commit comments