@@ -35,6 +35,7 @@ public class SparkSQLUtils {
3535 private static final Logger log = LoggerFactory .getLogger (SparkSQLUtils .class );
3636
3737 private static final Class <?> dataSourceV2RelationClass ;
38+ private static final Class <?> replaceDataClass ;
3839 private static final MethodHandle schemaMethod ;
3940 private static final MethodHandle nameMethod ;
4041 private static final MethodHandle propertiesMethod ;
@@ -51,9 +52,15 @@ private static Class<?> findTable() throws ClassNotFoundException {
5152 return Class .forName ("org.apache.spark.sql.connector.catalog.Table" );
5253 }
5354
55+ @ SuppressForbidden // Using reflection to avoid splitting the instrumentation once more
56+ private static Class <?> findReplaceData () throws ClassNotFoundException {
57+ return Class .forName ("org.apache.spark.sql.catalyst.plans.logical.ReplaceData" );
58+ }
59+
5460 static {
5561 Class <?> relationClassFound = null ;
5662 Class <?> tableClassFound = null ;
63+ Class <?> replaceDataClassFound = null ;
5764
5865 MethodHandle nameMethodFound = null ;
5966 MethodHandle schemaMethodFound = null ;
@@ -64,6 +71,7 @@ private static Class<?> findTable() throws ClassNotFoundException {
6471
6572 relationClassFound = findDataSourceV2Relation ();
6673 tableClassFound = findTable ();
74+ replaceDataClassFound = findReplaceData ();
6775
6876 schemaMethodFound =
6977 lookup .findVirtual (tableClassFound , "schema" , MethodType .methodType (StructType .class ));
@@ -76,6 +84,7 @@ private static Class<?> findTable() throws ClassNotFoundException {
7684 }
7785
7886 dataSourceV2RelationClass = relationClassFound ;
87+ replaceDataClass = replaceDataClassFound ;
7988 tableClass = tableClassFound ;
8089 schemaMethod = schemaMethodFound ;
8190 nameMethod = nameMethodFound ;
@@ -313,7 +322,8 @@ public DataSourceV2Relation apply(LogicalPlan x) {
313322 public boolean isDefinedAt (LogicalPlan x ) {
314323 return x instanceof DataSourceV2Relation
315324 || (x instanceof AppendData
316- && ((AppendData ) x ).table () instanceof DataSourceV2Relation );
325+ && ((AppendData ) x ).table () instanceof DataSourceV2Relation )
326+ || (replaceDataClass != null && replaceDataClass .isInstance (x ));
317327 }
318328
319329 @ Override
@@ -336,6 +346,28 @@ public LineageDataset apply(LogicalPlan x) {
336346 dataSourceV2RelationClass .getName ());
337347 return parseDataSourceV2Relation (table , "output" );
338348 }
349+ } else if (replaceDataClass != null && replaceDataClass .isInstance (x )) {
350+ log .info (
351+ "class {} is instance of {}" , x .getClass ().getName (), replaceDataClass .getName ());
352+
353+ try {
354+ if (x .getClass ().getMethod ("table" ) != null ) {
355+ Object table = x .getClass ().getMethod ("table" ).invoke (x );
356+ if (table != null
357+ && dataSourceV2RelationClass != null
358+ && dataSourceV2RelationClass .isInstance (table )) {
359+ return parseDataSourceV2Relation (table , "output" );
360+ } else {
361+ log .info (
362+ "table is null or not instance of {}, cannot parse current LogicalPlan" ,
363+ dataSourceV2RelationClass .getName ());
364+ }
365+ } else {
366+ log .info ("method table does not exist for {}" , x .getClass ().getName ());
367+ }
368+ } catch (Throwable ignored ) {
369+ log .info ("Error while converting logical plan to dataset" , ignored );
370+ }
339371 }
340372 return null ;
341373 }
0 commit comments