[ 
https://issues.apache.org/jira/browse/SPARK-58318?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Marc Le Bihan updated SPARK-58318:
----------------------------------
    Description: 
I'm following a {{String[]}} of competencies codes, at their indexes :
{code:java}
codesCompetences = (size = 121)
 0 = "C1005"  1 = "C1010"  2 = "C1015"  3 = "C1020"  4 = "C1025"
 5 = "C1030"  6 = "C1035"  7 = "C1040"  8 = "C1045"  9 = "C1505"
 10 = "C1510"  11 = "C1515"  12 = "C1520"  13 = "C2000"  14 = "C2005"
 15 = "C2010"  16 = "C2015"  17 = "C2020"  18 = "C2025"  19 = "C2030"
 20 = "C2035"  21 = "C2040"  22 = "C2045"  23 = "C2050"  24 = "C2055"
 25 = "C2060"  26 = "C2065"  27 = "C2070"  28 = "C2075"  29 = "C2080"
 30 = "C2085"  31 = "C2090"  32 = "C2095"  33 = "C2096"  34 = "C2500"
 35 = "C2505"  36 = "C2510"  37 = "C3000"  38 = "C3005"  39 = "C3010"
 40 = "C3015"  41 = "C3020"  42 = "C3025"  43 = "C3030"  44 = "C3035"
 45 = "C3040"  46 = "C3045"  47 = "C3050"  48 = "C3055"  49 = "C3060"
 50 = "C3500"  51 = "C4000"  52 = "C4005"  53 = "C4010"  54 = "C4500"
 55 = "C4505" 56 = "C4510"  57 = "C4515"  58 = "C4520"  59 = "C5000"
 60 = "C5005"  61 = "C5010"  62 = "C5015"  63 = "C5020"  64 = "C5025"
 65 = "C5030"  66 = "C5035"  67 = "C5040"  68 = "C5045"  69 = "C5050"
 70 = "C5500"  71 = "C5505"  72 = "C5510"  73 = "C5515"  74 = "C5520"
 75 = "C5525"  76 = "C5530"  77 = "C5535"  78 = "C5540"  79 = "C6000"
 80 = "C6005"  81 = "C6010"  82 = "C6015"  83 = "C6020"  84 = "C6025"
 85 = "C6030"  86 = "C6035"  87 = "C6040"  88 = "C6045"  89 = "C6055"
 90 = "C6060"  91 = "C6065"  92 = "C6070"  93 = "C6075"  94 = "C6500"
 95 = "C6505"  96 = "C6510"  97 = "C6515"  98 = "C6520"  99 = "C6525"
 100 = "C6530"  101 = "C6535"  102 = "C7000"  103 = "C7500"  104 = "C7505"
 105 = "C7510"  106 = "C7515"  107 = "C7520"  108 = "C7525"  109 = "C7530"
 110 = "C7535"  111 = "C7540"  112 = "C7541"  113 = "C7545"  114 = "C7546"
 115 = "C7550"  116 = "C7555"  117 = "C7560"  118 = "C7565"  119 = "C7570"
 120 = "C7575 {code}
With them, I'm converting values of columns coming from a CSV file:
{code:java}
private Dataset<Row> 
extraireCompetencesDelegueesEtInteretCommunautaire(Dataset<Row> dataset, int 
anneeCog) {
   // Ces valeurs sont celles qu'un distinct() montre possibles sur les 
colonnes du fichier csv d'entrée.
   final String COMPETENCE_DELEGUEE = "délégué";
   final String COMPETENCE_INTERET_COMMUNAUTAIRE = "avec intérêt 
communautaire";   

   List<String> codesCompetences = 
this.datasetCompetence.codesCompetencesAsList(anneeCog);   

   for(String codeCompetence : codesCompetences) {
      Column colCompetence = new Column(codeCompetence);      

      // Créer le champ Cxxx_Deleguee et le one hot encoder en "1" ou "0" selon 
que la valeur associée au code compétence vaut 'délégué' ou pas.
      Column competenceDeleguee = 
when(colCompetence.equalTo(COMPETENCE_DELEGUEE), lit("1")).otherwise(lit("0"));
      dataset = dataset.withColumn(codeCompetence + "_Deleguee", 
competenceDeleguee);     

      // Créer le champ Cxxx_InteretCommunautaire et le one hot encoder en "1" 
ou "0" selon que la valeur associée au code compétence vaut 'avec intérêt 
communautaire' ou pas.
      Column competenceInteretCommunautaire = 
when(colCompetence.equalTo(COMPETENCE_INTERET_COMMUNAUTAIRE), 
lit("1")).otherwise(lit("0"));
      dataset = dataset.withColumn(codeCompetence + "_InteretCommunautaire", 
competenceInteretCommunautaire);      

      // one hot encoder la présence de la compétence
      Column encoding = when(colCompetence.isin(OUI, COMPETENCE_DELEGUEE, 
COMPETENCE_INTERET_COMMUNAUTAIRE), lit("1"))
         .when(colCompetence.equalTo(NON), lit("0"))
         .otherwise(colCompetence);      

      dataset = dataset.withColumn(codeCompetence, encoding);
      LOGGER.info("added: '{}'", encoding);
   }   

   return dataset;
}
{code}
This loop adds to the {{Dataset}} some columns each time,. Among them one is :
{code:java}
added: 'CASE WHEN in(C6525, 'OUI', 'délégué', 'avec intérêt communautaire') 
THEN '1' WHEN =(C6525, 'NON') THEN '0' ELSE C6525 END'{code}
and it's the last log shown before a:
{code:java}
java.lang.StackOverflowError
    at java.base/java.lang.ref.Reference.refersToImpl(Reference.java:384)
    at java.base/java.lang.ref.Reference.refersTo(Reference.java:375)
    at java.base/java.lang.ThreadLocal$ThreadLocalMap.set(ThreadLocal.java:539)
    at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:243)
    at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:229)
    at org.apache.spark.sql.catalyst.trees.CurrentOrigin$.set(origin.scala:93)
    at 
org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:105)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:495)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$transformDownWithPruning$3(TreeNode.scala:500)
    at 
org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren(TreeNode.scala:1268)
    at 
org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren$(TreeNode.scala:1267)
    at 
org.apache.spark.sql.catalyst.expressions.UnaryExpression.mapChildren(Expression.scala:596)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:500)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$transformExpressionsDownWithPruning$1(QueryPlan.scala:223)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$1(QueryPlan.scala:264)
    at 
org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:107)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpression$1(QueryPlan.scala:264)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:276)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$4(QueryPlan.scala:282)
    at scala.collection.immutable.List.map(List.scala:236)
    at scala.collection.immutable.List.map(List.scala:79)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:282)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$5(QueryPlan.scala:287)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.mapProductIterator(TreeNode.scala:337)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.mapExpressions(QueryPlan.scala:287)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsDownWithPruning(QueryPlan.scala:223)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsWithPruning(QueryPlan.scala:194)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressions(QueryPlan.scala:172)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:240)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
    at scala.collection.immutable.Vector.foreach(Vector.scala:2125)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:232)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
[...] {code}
What I've noticed during my debugs is that:
 
 * If I do a step over step debugging, without allowing my program to resume 
from `C6525`, I can pursue through `C6530`, `C6535`... But as soon as do a 
Resume program, the stack overflow happens.

So I guess it's an helper thread that starts to work on the request being 
prepared that causes the trouble.

The problem didn't exist with Spark {{4.1.1}} I was using before, with {{Java 
21}} then.

Remark: 
this code is included in a larger one, in the {{if (this.anneeCOG >= 2025)} 
below:

 {code:java}
@Override
public Dataset<Row> get() {
   LOGGER.info("Constitution du dataset des périmètres de groupements 
(intercommunalités seulement : {}) par {} pour l'année {}...",
      this.epciSeulement, this.tri, this.anneeCOG);   
this.session.sparkContext().setJobDescription("EPCIPerimetreWorker");
   this.session.sparkContext().setLocalProperty("callSite.short", toString());  
 

   // Obtention des SIREN des communes d'après le COG.
   Dataset<Row> sirenCommunes = 
this.datasetSirenCommunaux.rowSirenCommunes(this.options, this.historique, new 
SirenCommunesTriSiren(), this.anneeCOG);   

   Dataset<Row> perimetres = this.loader.loadOpenData(this.anneeCOG);   

   // Corriger les catégories de communes "Commune" en commune
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Commune")), 
lit("commune"))
      .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   // Celles "Groupement" 
en groupement
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Groupement")), 
lit("groupement"))
         .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   

   // Et celles "Autre organisme" en autre organisme
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Autre organisme")), 
lit("autre organisme"))
         .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   perimetres = 
perimetres.persist();   

   boolean versionBanatic2024etAnterieure = this.anneeCOG <= 2024;

   PerimetreAdaptateurAnnuel adaptateurAnnuel = versionBanatic2024etAnterieure 
? new PerimetreAdaptateurAnnuel2024EtAnterieur() : new 
PerimetreAdaptateurAnnuel2025EtPosterieur();   

   // Si l'année porte sur une version de fichiers BANATIC ancienne,
   // les champs de code portant sur les région, département, commune sont 
encodés sous la forme 'code - libellé'
   perimetres = 
adaptateurAnnuel.extraireCodesRegionDepartementArrondissementSiren(perimetres, 
this.session);
   perimetres = retrouverRegion(perimetres, sirenCommunes, this.anneeCOG);  

   // TODO : ici, est-ce sûr que c'est POPULATION_TOTALE ?
   perimetres = perimetres.withColumnRenamed(POPULATION_TOTALE.champ(), 
POPULATION_GROUPEMENT.champ());   

   perimetres = joinSirenCommunes(perimetres);
   perimetres = adaptateurAnnuel.codePostalEtVilleAdministrative(perimetres);  

   Column joinCommuneSiege = 
SIREN_COMMUNE_SIEGE.col(perimetres).equalTo(SIREN_COMMUNE.col(sirenCommunes));  
 perimetres = perimetres.join(sirenCommunes, joinCommuneSiege, LEFT_OUTER)
      .withColumnRenamed(CODE_COMMUNE.champ(), CODE_COMMUNE_SIEGE.champ())
      .withColumnRenamed(POPULATION_TOTALE.champ(), 
POPULATION_COMMUNE_SIEGE_TOTALE.champ())
      .withColumnRenamed(POPULATION_MUNICIPALE.champ(), 
POPULATION_COMMUNE_SIEGE_MUNICIPALE.champ())
      .withColumnRenamed(POPULATION_COMPTEE_A_PART.champ(), 
POPULATION_COMMUNE_SIEGE_COMPTEE_A_PART.champ())
      .drop(NOM_REGION.champ())
      .drop(CODE_REGION.champ())
      .drop(CODE_DEPARTEMENT.champ())
      .drop(NOM_DEPARTEMENT.champ())
      .drop(SIREN_COMMUNE.champ());   

   perimetres = adaptateurAnnuel.codePostalEtVilleSiege(perimetres);   

   // FIXME En 2019, Choisy-le-Roi est inscrit comme EPT lié à la fois à 
Grand-Orly Seine, ce qui est exact, mais aussi d'Est-Ensemble comme EPT, ce qui 
n'est pas vrai.
   Column eptChoisyLeRoiConfusion = 
NATURE_JURIDIQUE.col().equalTo("EPT").and(SIREN_GROUPEMENT.col(perimetres).equalTo("200057875"));
   

   if (this.epciSeulement) {
      perimetres = perimetres.filter(NATURE_JURIDIQUE.col().isin("CA", "CC", 
"CU", "EPT", "METRO", "MET69")
         .and(not(eptChoisyLeRoiConfusion)));
   }   

   if (this.anneeCOG >= 2025) {
      perimetres = hotEncodingAvecNull(perimetres, 
SYNDICAT_A_LA_CARTE.champ()); // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, INTERDEPARTEMENTAL.champ()); 
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, ZONE_DE_MONTAGNE.champ());   
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, GESTION_DES_EAUX.champ());   
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, 
ETABLISSEMENT_PUBLIC_TERRITORIAL_DE_BASSIN.champ()); // Contient des valeurs 
nulles
      perimetres = hotEncodingAvecNull(perimetres, 
TAXE_ENLEVEMENT_ORDURES_MENAGERES.champ());          // Sans valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, 
REDEVANCE_ENLEVEMENT_ORDURES_MENAGERES.champ());     // Sans valeurs nulles
      perimetres = 
extraireCompetencesDelegueesEtInteretCommunautaire(perimetres, this.anneeCOG);
   }   

   perimetres = perimetres.filter((FilterFunction<Row>) perimetre -> 
this.validator.validerPerimetre(this.historique, perimetre, this.anneeCOG));
   
   perimetres = ajouterCompetencesPasEncoreExistantesOuDisparues(perimetres, 
this.anneeCOG);   

   List<Column> colonnesSelect = adaptateurAnnuel.select(perimetres, 
this.datasetCompetence, this.anneeCOG);
   perimetres = perimetres.select(colonnesSelect.toArray(new Column[]{}));
   return perimetres;
}{code}


  was:
I'm following a {{String[]}} of competencies codes, at their indexes :
{code:java}
codesCompetences = (size = 121)
 0 = "C1005"  1 = "C1010"  2 = "C1015"  3 = "C1020"  4 = "C1025"
 5 = "C1030"  6 = "C1035"  7 = "C1040"  8 = "C1045"  9 = "C1505"
 10 = "C1510"  11 = "C1515"  12 = "C1520"  13 = "C2000"  14 = "C2005"
 15 = "C2010"  16 = "C2015"  17 = "C2020"  18 = "C2025"  19 = "C2030"
 20 = "C2035"  21 = "C2040"  22 = "C2045"  23 = "C2050"  24 = "C2055"
 25 = "C2060"  26 = "C2065"  27 = "C2070"  28 = "C2075"  29 = "C2080"
 30 = "C2085"  31 = "C2090"  32 = "C2095"  33 = "C2096"  34 = "C2500"
 35 = "C2505"  36 = "C2510"  37 = "C3000"  38 = "C3005"  39 = "C3010"
 40 = "C3015"  41 = "C3020"  42 = "C3025"  43 = "C3030"  44 = "C3035"
 45 = "C3040"  46 = "C3045"  47 = "C3050"  48 = "C3055"  49 = "C3060"
 50 = "C3500"  51 = "C4000"  52 = "C4005"  53 = "C4010"  54 = "C4500"
 55 = "C4505" 56 = "C4510"  57 = "C4515"  58 = "C4520"  59 = "C5000"
 60 = "C5005"  61 = "C5010"  62 = "C5015"  63 = "C5020"  64 = "C5025"
 65 = "C5030"  66 = "C5035"  67 = "C5040"  68 = "C5045"  69 = "C5050"
 70 = "C5500"  71 = "C5505"  72 = "C5510"  73 = "C5515"  74 = "C5520"
 75 = "C5525"  76 = "C5530"  77 = "C5535"  78 = "C5540"  79 = "C6000"
 80 = "C6005"  81 = "C6010"  82 = "C6015"  83 = "C6020"  84 = "C6025"
 85 = "C6030"  86 = "C6035"  87 = "C6040"  88 = "C6045"  89 = "C6055"
 90 = "C6060"  91 = "C6065"  92 = "C6070"  93 = "C6075"  94 = "C6500"
 95 = "C6505"  96 = "C6510"  97 = "C6515"  98 = "C6520"  99 = "C6525"
 100 = "C6530"  101 = "C6535"  102 = "C7000"  103 = "C7500"  104 = "C7505"
 105 = "C7510"  106 = "C7515"  107 = "C7520"  108 = "C7525"  109 = "C7530"
 110 = "C7535"  111 = "C7540"  112 = "C7541"  113 = "C7545"  114 = "C7546"
 115 = "C7550"  116 = "C7555"  117 = "C7560"  118 = "C7565"  119 = "C7570"
 120 = "C7575 {code}
With them, I'm converting values of columns coming from a CSV file:
{code:java}
private Dataset<Row> 
extraireCompetencesDelegueesEtInteretCommunautaire(Dataset<Row> dataset, int 
anneeCog) {
   // Ces valeurs sont celles qu'un distinct() montre possibles sur les 
colonnes du fichier csv d'entrée.
   final String COMPETENCE_DELEGUEE = "délégué";
   final String COMPETENCE_INTERET_COMMUNAUTAIRE = "avec intérêt 
communautaire";   

   List<String> codesCompetences = 
this.datasetCompetence.codesCompetencesAsList(anneeCog);   

   for(String codeCompetence : codesCompetences) {
      Column colCompetence = new Column(codeCompetence);      

      // Créer le champ Cxxx_Deleguee et le one hot encoder en "1" ou "0" selon 
que la valeur associée au code compétence vaut 'délégué' ou pas.
      Column competenceDeleguee = 
when(colCompetence.equalTo(COMPETENCE_DELEGUEE), lit("1")).otherwise(lit("0"));
      dataset = dataset.withColumn(codeCompetence + "_Deleguee", 
competenceDeleguee);     

      // Créer le champ Cxxx_InteretCommunautaire et le one hot encoder en "1" 
ou "0" selon que la valeur associée au code compétence vaut 'avec intérêt 
communautaire' ou pas.
      Column competenceInteretCommunautaire = 
when(colCompetence.equalTo(COMPETENCE_INTERET_COMMUNAUTAIRE), 
lit("1")).otherwise(lit("0"));
      dataset = dataset.withColumn(codeCompetence + "_InteretCommunautaire", 
competenceInteretCommunautaire);      

      // one hot encoder la présence de la compétence
      Column encoding = when(colCompetence.isin(OUI, COMPETENCE_DELEGUEE, 
COMPETENCE_INTERET_COMMUNAUTAIRE), lit("1"))
         .when(colCompetence.equalTo(NON), lit("0"))
         .otherwise(colCompetence);      

      dataset = dataset.withColumn(codeCompetence, encoding);
      LOGGER.info("added: '{}'", encoding);
   }   

   return dataset;
}
{code}
This loop adds to the {{Dataset}} some columns each time,. Among them one is :
{code:java}
added: 'CASE WHEN in(C6525, 'OUI', 'délégué', 'avec intérêt communautaire') 
THEN '1' WHEN =(C6525, 'NON') THEN '0' ELSE C6525 END'{code}
and it's the last log shown before a:
{code:java}
java.lang.StackOverflowError
    at java.base/java.lang.ref.Reference.refersToImpl(Reference.java:384)
    at java.base/java.lang.ref.Reference.refersTo(Reference.java:375)
    at java.base/java.lang.ThreadLocal$ThreadLocalMap.set(ThreadLocal.java:539)
    at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:243)
    at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:229)
    at org.apache.spark.sql.catalyst.trees.CurrentOrigin$.set(origin.scala:93)
    at 
org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:105)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:495)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$transformDownWithPruning$3(TreeNode.scala:500)
    at 
org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren(TreeNode.scala:1268)
    at 
org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren$(TreeNode.scala:1267)
    at 
org.apache.spark.sql.catalyst.expressions.UnaryExpression.mapChildren(Expression.scala:596)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:500)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$transformExpressionsDownWithPruning$1(QueryPlan.scala:223)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$1(QueryPlan.scala:264)
    at 
org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:107)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpression$1(QueryPlan.scala:264)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:276)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$4(QueryPlan.scala:282)
    at scala.collection.immutable.List.map(List.scala:236)
    at scala.collection.immutable.List.map(List.scala:79)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:282)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$5(QueryPlan.scala:287)
    at 
org.apache.spark.sql.catalyst.trees.TreeNode.mapProductIterator(TreeNode.scala:337)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.mapExpressions(QueryPlan.scala:287)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsDownWithPruning(QueryPlan.scala:223)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsWithPruning(QueryPlan.scala:194)
    at 
org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressions(QueryPlan.scala:172)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:240)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
    at scala.collection.immutable.Vector.foreach(Vector.scala:2125)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:232)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
    at 
org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
[...] {code}
What I've noticed during my debugs is that:
 
 * If I do a step over step debugging, without allowing my program to resume 
from `C6525`, I can pursue through `C6530`, `C6535`... But as soon as do a 
Resume program, the stack overflow happens.

* If I assign each of these new columns to {{lit("0")}}, avoiding these 
{{when...otherwise}}, the StackOverflow comes after the loop, but it comes 
quickly after. So eventually, it triggers all the time.

So I guess it's an helper thread that starts to work on the request being 
prepared that causes the trouble.

The problem didn't exist with Spark {{4.1.1}} I was using before, with {{Java 
21}} then.

Remark: 
this code is included in a larger one, in the {{if (this.anneeCOG >= 2025)} 
below:

 {code:java}
@Override
public Dataset<Row> get() {
   LOGGER.info("Constitution du dataset des périmètres de groupements 
(intercommunalités seulement : {}) par {} pour l'année {}...",
      this.epciSeulement, this.tri, this.anneeCOG);   
this.session.sparkContext().setJobDescription("EPCIPerimetreWorker");
   this.session.sparkContext().setLocalProperty("callSite.short", toString());  
 

   // Obtention des SIREN des communes d'après le COG.
   Dataset<Row> sirenCommunes = 
this.datasetSirenCommunaux.rowSirenCommunes(this.options, this.historique, new 
SirenCommunesTriSiren(), this.anneeCOG);   

   Dataset<Row> perimetres = this.loader.loadOpenData(this.anneeCOG);   

   // Corriger les catégories de communes "Commune" en commune
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Commune")), 
lit("commune"))
      .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   // Celles "Groupement" 
en groupement
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Groupement")), 
lit("groupement"))
         .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   

   // Et celles "Autre organisme" en autre organisme
   perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
      when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Autre organisme")), 
lit("autre organisme"))
         .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   perimetres = 
perimetres.persist();   

   boolean versionBanatic2024etAnterieure = this.anneeCOG <= 2024;

   PerimetreAdaptateurAnnuel adaptateurAnnuel = versionBanatic2024etAnterieure 
? new PerimetreAdaptateurAnnuel2024EtAnterieur() : new 
PerimetreAdaptateurAnnuel2025EtPosterieur();   

   // Si l'année porte sur une version de fichiers BANATIC ancienne,
   // les champs de code portant sur les région, département, commune sont 
encodés sous la forme 'code - libellé'
   perimetres = 
adaptateurAnnuel.extraireCodesRegionDepartementArrondissementSiren(perimetres, 
this.session);
   perimetres = retrouverRegion(perimetres, sirenCommunes, this.anneeCOG);  

   // TODO : ici, est-ce sûr que c'est POPULATION_TOTALE ?
   perimetres = perimetres.withColumnRenamed(POPULATION_TOTALE.champ(), 
POPULATION_GROUPEMENT.champ());   

   perimetres = joinSirenCommunes(perimetres);
   perimetres = adaptateurAnnuel.codePostalEtVilleAdministrative(perimetres);  

   Column joinCommuneSiege = 
SIREN_COMMUNE_SIEGE.col(perimetres).equalTo(SIREN_COMMUNE.col(sirenCommunes));  
 perimetres = perimetres.join(sirenCommunes, joinCommuneSiege, LEFT_OUTER)
      .withColumnRenamed(CODE_COMMUNE.champ(), CODE_COMMUNE_SIEGE.champ())
      .withColumnRenamed(POPULATION_TOTALE.champ(), 
POPULATION_COMMUNE_SIEGE_TOTALE.champ())
      .withColumnRenamed(POPULATION_MUNICIPALE.champ(), 
POPULATION_COMMUNE_SIEGE_MUNICIPALE.champ())
      .withColumnRenamed(POPULATION_COMPTEE_A_PART.champ(), 
POPULATION_COMMUNE_SIEGE_COMPTEE_A_PART.champ())
      .drop(NOM_REGION.champ())
      .drop(CODE_REGION.champ())
      .drop(CODE_DEPARTEMENT.champ())
      .drop(NOM_DEPARTEMENT.champ())
      .drop(SIREN_COMMUNE.champ());   

   perimetres = adaptateurAnnuel.codePostalEtVilleSiege(perimetres);   

   // FIXME En 2019, Choisy-le-Roi est inscrit comme EPT lié à la fois à 
Grand-Orly Seine, ce qui est exact, mais aussi d'Est-Ensemble comme EPT, ce qui 
n'est pas vrai.
   Column eptChoisyLeRoiConfusion = 
NATURE_JURIDIQUE.col().equalTo("EPT").and(SIREN_GROUPEMENT.col(perimetres).equalTo("200057875"));
   

   if (this.epciSeulement) {
      perimetres = perimetres.filter(NATURE_JURIDIQUE.col().isin("CA", "CC", 
"CU", "EPT", "METRO", "MET69")
         .and(not(eptChoisyLeRoiConfusion)));
   }   

   if (this.anneeCOG >= 2025) {
      perimetres = hotEncodingAvecNull(perimetres, 
SYNDICAT_A_LA_CARTE.champ()); // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, INTERDEPARTEMENTAL.champ()); 
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, ZONE_DE_MONTAGNE.champ());   
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, GESTION_DES_EAUX.champ());   
 // Contient des valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, 
ETABLISSEMENT_PUBLIC_TERRITORIAL_DE_BASSIN.champ()); // Contient des valeurs 
nulles
      perimetres = hotEncodingAvecNull(perimetres, 
TAXE_ENLEVEMENT_ORDURES_MENAGERES.champ());          // Sans valeurs nulles
      perimetres = hotEncodingAvecNull(perimetres, 
REDEVANCE_ENLEVEMENT_ORDURES_MENAGERES.champ());     // Sans valeurs nulles
      perimetres = 
extraireCompetencesDelegueesEtInteretCommunautaire(perimetres, this.anneeCOG);
   }   

   perimetres = perimetres.filter((FilterFunction<Row>) perimetre -> 
this.validator.validerPerimetre(this.historique, perimetre, this.anneeCOG));
   
   perimetres = ajouterCompetencesPasEncoreExistantesOuDisparues(perimetres, 
this.anneeCOG);   

   List<Column> colonnesSelect = adaptateurAnnuel.select(perimetres, 
this.datasetCompetence, this.anneeCOG);
   perimetres = perimetres.select(colonnesSelect.toArray(new Column[]{}));
   return perimetres;
}{code}



> SQL Catalyst 4.2.0 causes a StackOverflow error when it attempts to optimize 
> a request it is preparing
> ------------------------------------------------------------------------------------------------------
>
>                 Key: SPARK-58318
>                 URL: https://issues.apache.org/jira/browse/SPARK-58318
>             Project: Spark
>          Issue Type: Bug
>          Components: SQL
>    Affects Versions: 4.2.0
>         Environment: Debian 13
> Spark 4.2.0
> Java 25
>            Reporter: Marc Le Bihan
>            Priority: Major
>
> I'm following a {{String[]}} of competencies codes, at their indexes :
> {code:java}
> codesCompetences = (size = 121)
>  0 = "C1005"  1 = "C1010"  2 = "C1015"  3 = "C1020"  4 = "C1025"
>  5 = "C1030"  6 = "C1035"  7 = "C1040"  8 = "C1045"  9 = "C1505"
>  10 = "C1510"  11 = "C1515"  12 = "C1520"  13 = "C2000"  14 = "C2005"
>  15 = "C2010"  16 = "C2015"  17 = "C2020"  18 = "C2025"  19 = "C2030"
>  20 = "C2035"  21 = "C2040"  22 = "C2045"  23 = "C2050"  24 = "C2055"
>  25 = "C2060"  26 = "C2065"  27 = "C2070"  28 = "C2075"  29 = "C2080"
>  30 = "C2085"  31 = "C2090"  32 = "C2095"  33 = "C2096"  34 = "C2500"
>  35 = "C2505"  36 = "C2510"  37 = "C3000"  38 = "C3005"  39 = "C3010"
>  40 = "C3015"  41 = "C3020"  42 = "C3025"  43 = "C3030"  44 = "C3035"
>  45 = "C3040"  46 = "C3045"  47 = "C3050"  48 = "C3055"  49 = "C3060"
>  50 = "C3500"  51 = "C4000"  52 = "C4005"  53 = "C4010"  54 = "C4500"
>  55 = "C4505" 56 = "C4510"  57 = "C4515"  58 = "C4520"  59 = "C5000"
>  60 = "C5005"  61 = "C5010"  62 = "C5015"  63 = "C5020"  64 = "C5025"
>  65 = "C5030"  66 = "C5035"  67 = "C5040"  68 = "C5045"  69 = "C5050"
>  70 = "C5500"  71 = "C5505"  72 = "C5510"  73 = "C5515"  74 = "C5520"
>  75 = "C5525"  76 = "C5530"  77 = "C5535"  78 = "C5540"  79 = "C6000"
>  80 = "C6005"  81 = "C6010"  82 = "C6015"  83 = "C6020"  84 = "C6025"
>  85 = "C6030"  86 = "C6035"  87 = "C6040"  88 = "C6045"  89 = "C6055"
>  90 = "C6060"  91 = "C6065"  92 = "C6070"  93 = "C6075"  94 = "C6500"
>  95 = "C6505"  96 = "C6510"  97 = "C6515"  98 = "C6520"  99 = "C6525"
>  100 = "C6530"  101 = "C6535"  102 = "C7000"  103 = "C7500"  104 = "C7505"
>  105 = "C7510"  106 = "C7515"  107 = "C7520"  108 = "C7525"  109 = "C7530"
>  110 = "C7535"  111 = "C7540"  112 = "C7541"  113 = "C7545"  114 = "C7546"
>  115 = "C7550"  116 = "C7555"  117 = "C7560"  118 = "C7565"  119 = "C7570"
>  120 = "C7575 {code}
> With them, I'm converting values of columns coming from a CSV file:
> {code:java}
> private Dataset<Row> 
> extraireCompetencesDelegueesEtInteretCommunautaire(Dataset<Row> dataset, int 
> anneeCog) {
>    // Ces valeurs sont celles qu'un distinct() montre possibles sur les 
> colonnes du fichier csv d'entrée.
>    final String COMPETENCE_DELEGUEE = "délégué";
>    final String COMPETENCE_INTERET_COMMUNAUTAIRE = "avec intérêt 
> communautaire";   
>    List<String> codesCompetences = 
> this.datasetCompetence.codesCompetencesAsList(anneeCog);   
>    for(String codeCompetence : codesCompetences) {
>       Column colCompetence = new Column(codeCompetence);      
>       // Créer le champ Cxxx_Deleguee et le one hot encoder en "1" ou "0" 
> selon que la valeur associée au code compétence vaut 'délégué' ou pas.
>       Column competenceDeleguee = 
> when(colCompetence.equalTo(COMPETENCE_DELEGUEE), 
> lit("1")).otherwise(lit("0"));
>       dataset = dataset.withColumn(codeCompetence + "_Deleguee", 
> competenceDeleguee);     
>       // Créer le champ Cxxx_InteretCommunautaire et le one hot encoder en 
> "1" ou "0" selon que la valeur associée au code compétence vaut 'avec intérêt 
> communautaire' ou pas.
>       Column competenceInteretCommunautaire = 
> when(colCompetence.equalTo(COMPETENCE_INTERET_COMMUNAUTAIRE), 
> lit("1")).otherwise(lit("0"));
>       dataset = dataset.withColumn(codeCompetence + "_InteretCommunautaire", 
> competenceInteretCommunautaire);      
>       // one hot encoder la présence de la compétence
>       Column encoding = when(colCompetence.isin(OUI, COMPETENCE_DELEGUEE, 
> COMPETENCE_INTERET_COMMUNAUTAIRE), lit("1"))
>          .when(colCompetence.equalTo(NON), lit("0"))
>          .otherwise(colCompetence);      
>       dataset = dataset.withColumn(codeCompetence, encoding);
>       LOGGER.info("added: '{}'", encoding);
>    }   
>    return dataset;
> }
> {code}
> This loop adds to the {{Dataset}} some columns each time,. Among them one is :
> {code:java}
> added: 'CASE WHEN in(C6525, 'OUI', 'délégué', 'avec intérêt communautaire') 
> THEN '1' WHEN =(C6525, 'NON') THEN '0' ELSE C6525 END'{code}
> and it's the last log shown before a:
> {code:java}
> java.lang.StackOverflowError
>     at java.base/java.lang.ref.Reference.refersToImpl(Reference.java:384)
>     at java.base/java.lang.ref.Reference.refersTo(Reference.java:375)
>     at 
> java.base/java.lang.ThreadLocal$ThreadLocalMap.set(ThreadLocal.java:539)
>     at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:243)
>     at java.base/java.lang.ThreadLocal.set(ThreadLocal.java:229)
>     at org.apache.spark.sql.catalyst.trees.CurrentOrigin$.set(origin.scala:93)
>     at 
> org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:105)
>     at 
> org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:495)
>     at 
> org.apache.spark.sql.catalyst.trees.TreeNode.$anonfun$transformDownWithPruning$3(TreeNode.scala:500)
>     at 
> org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren(TreeNode.scala:1268)
>     at 
> org.apache.spark.sql.catalyst.trees.UnaryLike.mapChildren$(TreeNode.scala:1267)
>     at 
> org.apache.spark.sql.catalyst.expressions.UnaryExpression.mapChildren(Expression.scala:596)
>     at 
> org.apache.spark.sql.catalyst.trees.TreeNode.transformDownWithPruning(TreeNode.scala:500)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$transformExpressionsDownWithPruning$1(QueryPlan.scala:223)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$1(QueryPlan.scala:264)
>     at 
> org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(origin.scala:107)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpression$1(QueryPlan.scala:264)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:276)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$4(QueryPlan.scala:282)
>     at scala.collection.immutable.List.map(List.scala:236)
>     at scala.collection.immutable.List.map(List.scala:79)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.recursiveTransform$1(QueryPlan.scala:282)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.$anonfun$mapExpressions$5(QueryPlan.scala:287)
>     at 
> org.apache.spark.sql.catalyst.trees.TreeNode.mapProductIterator(TreeNode.scala:337)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.mapExpressions(QueryPlan.scala:287)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsDownWithPruning(QueryPlan.scala:223)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressionsWithPruning(QueryPlan.scala:194)
>     at 
> org.apache.spark.sql.catalyst.plans.QueryPlan.transformExpressions(QueryPlan.scala:172)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:240)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
>     at scala.collection.immutable.Vector.foreach(Vector.scala:2125)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicate(DeduplicateRelations.scala:232)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.deduplicateAndRenew(DeduplicateRelations.scala:323)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.org$apache$spark$sql$catalyst$analysis$DeduplicateRelations$$renewDuplicatedRelations(DeduplicateRelations.scala:126)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1(DeduplicateRelations.scala:233)
>     at 
> org.apache.spark.sql.catalyst.analysis.DeduplicateRelations$.$anonfun$deduplicate$1$adapted(DeduplicateRelations.scala:232)
> [...] {code}
> What I've noticed during my debugs is that:
>  
>  * If I do a step over step debugging, without allowing my program to resume 
> from `C6525`, I can pursue through `C6530`, `C6535`... But as soon as do a 
> Resume program, the stack overflow happens.
> So I guess it's an helper thread that starts to work on the request being 
> prepared that causes the trouble.
> The problem didn't exist with Spark {{4.1.1}} I was using before, with {{Java 
> 21}} then.
> Remark: 
> this code is included in a larger one, in the {{if (this.anneeCOG >= 2025)} 
> below:
>  {code:java}
> @Override
> public Dataset<Row> get() {
>    LOGGER.info("Constitution du dataset des périmètres de groupements 
> (intercommunalités seulement : {}) par {} pour l'année {}...",
>       this.epciSeulement, this.tri, this.anneeCOG);   
> this.session.sparkContext().setJobDescription("EPCIPerimetreWorker");
>    this.session.sparkContext().setLocalProperty("callSite.short", 
> toString());   
>    // Obtention des SIREN des communes d'après le COG.
>    Dataset<Row> sirenCommunes = 
> this.datasetSirenCommunaux.rowSirenCommunes(this.options, this.historique, 
> new SirenCommunesTriSiren(), this.anneeCOG);   
>    Dataset<Row> perimetres = this.loader.loadOpenData(this.anneeCOG);   
>    // Corriger les catégories de communes "Commune" en commune
>    perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
>       when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Commune")), 
> lit("commune"))
>       .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   // Celles 
> "Groupement" en groupement
>    perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
>       when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Groupement")), 
> lit("groupement"))
>          .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   
>    // Et celles "Autre organisme" en autre organisme
>    perimetres = perimetres.withColumn(CATEGORIE_MEMBRES_GROUPEMENT.champ(),
>       when(CATEGORIE_MEMBRES_GROUPEMENT.col().equalTo(lit("Autre 
> organisme")), lit("autre organisme"))
>          .otherwise(CATEGORIE_MEMBRES_GROUPEMENT.col()));   perimetres = 
> perimetres.persist();   
>    boolean versionBanatic2024etAnterieure = this.anneeCOG <= 2024;
>    PerimetreAdaptateurAnnuel adaptateurAnnuel = 
> versionBanatic2024etAnterieure ? new 
> PerimetreAdaptateurAnnuel2024EtAnterieur() : new 
> PerimetreAdaptateurAnnuel2025EtPosterieur();   
>    // Si l'année porte sur une version de fichiers BANATIC ancienne,
>    // les champs de code portant sur les région, département, commune sont 
> encodés sous la forme 'code - libellé'
>    perimetres = 
> adaptateurAnnuel.extraireCodesRegionDepartementArrondissementSiren(perimetres,
>  this.session);
>    perimetres = retrouverRegion(perimetres, sirenCommunes, this.anneeCOG);  
>    // TODO : ici, est-ce sûr que c'est POPULATION_TOTALE ?
>    perimetres = perimetres.withColumnRenamed(POPULATION_TOTALE.champ(), 
> POPULATION_GROUPEMENT.champ());   
>    perimetres = joinSirenCommunes(perimetres);
>    perimetres = adaptateurAnnuel.codePostalEtVilleAdministrative(perimetres); 
>  
>    Column joinCommuneSiege = 
> SIREN_COMMUNE_SIEGE.col(perimetres).equalTo(SIREN_COMMUNE.col(sirenCommunes));
>    perimetres = perimetres.join(sirenCommunes, joinCommuneSiege, LEFT_OUTER)
>       .withColumnRenamed(CODE_COMMUNE.champ(), CODE_COMMUNE_SIEGE.champ())
>       .withColumnRenamed(POPULATION_TOTALE.champ(), 
> POPULATION_COMMUNE_SIEGE_TOTALE.champ())
>       .withColumnRenamed(POPULATION_MUNICIPALE.champ(), 
> POPULATION_COMMUNE_SIEGE_MUNICIPALE.champ())
>       .withColumnRenamed(POPULATION_COMPTEE_A_PART.champ(), 
> POPULATION_COMMUNE_SIEGE_COMPTEE_A_PART.champ())
>       .drop(NOM_REGION.champ())
>       .drop(CODE_REGION.champ())
>       .drop(CODE_DEPARTEMENT.champ())
>       .drop(NOM_DEPARTEMENT.champ())
>       .drop(SIREN_COMMUNE.champ());   
>    perimetres = adaptateurAnnuel.codePostalEtVilleSiege(perimetres);   
>    // FIXME En 2019, Choisy-le-Roi est inscrit comme EPT lié à la fois à 
> Grand-Orly Seine, ce qui est exact, mais aussi d'Est-Ensemble comme EPT, ce 
> qui n'est pas vrai.
>    Column eptChoisyLeRoiConfusion = 
> NATURE_JURIDIQUE.col().equalTo("EPT").and(SIREN_GROUPEMENT.col(perimetres).equalTo("200057875"));
>    
>    if (this.epciSeulement) {
>       perimetres = perimetres.filter(NATURE_JURIDIQUE.col().isin("CA", "CC", 
> "CU", "EPT", "METRO", "MET69")
>          .and(not(eptChoisyLeRoiConfusion)));
>    }   
>    if (this.anneeCOG >= 2025) {
>       perimetres = hotEncodingAvecNull(perimetres, 
> SYNDICAT_A_LA_CARTE.champ()); // Contient des valeurs nulles
>       perimetres = hotEncodingAvecNull(perimetres, 
> INTERDEPARTEMENTAL.champ());  // Contient des valeurs nulles
>       perimetres = hotEncodingAvecNull(perimetres, ZONE_DE_MONTAGNE.champ()); 
>    // Contient des valeurs nulles
>       perimetres = hotEncodingAvecNull(perimetres, GESTION_DES_EAUX.champ()); 
>    // Contient des valeurs nulles
>       perimetres = hotEncodingAvecNull(perimetres, 
> ETABLISSEMENT_PUBLIC_TERRITORIAL_DE_BASSIN.champ()); // Contient des valeurs 
> nulles
>       perimetres = hotEncodingAvecNull(perimetres, 
> TAXE_ENLEVEMENT_ORDURES_MENAGERES.champ());          // Sans valeurs nulles
>       perimetres = hotEncodingAvecNull(perimetres, 
> REDEVANCE_ENLEVEMENT_ORDURES_MENAGERES.champ());     // Sans valeurs nulles
>       perimetres = 
> extraireCompetencesDelegueesEtInteretCommunautaire(perimetres, this.anneeCOG);
>    }   
>    perimetres = perimetres.filter((FilterFunction<Row>) perimetre -> 
> this.validator.validerPerimetre(this.historique, perimetre, this.anneeCOG));
>    
>    perimetres = ajouterCompetencesPasEncoreExistantesOuDisparues(perimetres, 
> this.anneeCOG);   
>    List<Column> colonnesSelect = adaptateurAnnuel.select(perimetres, 
> this.datasetCompetence, this.anneeCOG);
>    perimetres = perimetres.select(colonnesSelect.toArray(new Column[]{}));
>    return perimetres;
> }{code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to