3232import java .util .Objects ;
3333import java .util .Properties ;
3434import java .util .Set ;
35+ import java .util .TreeMap ;
3536import java .util .stream .Collectors ;
3637
3738
3839import org .apache .commons .collections4 .CollectionUtils ;
3940import org .apache .commons .lang3 .StringUtils ;
41+ import org .apache .commons .lang3 .tuple .Pair ;
4042import org .apache .hadoop .conf .Configuration ;
4143import org .apache .hadoop .fs .FileStatus ;
4244import org .apache .hadoop .fs .FileSystem ;
@@ -113,7 +115,10 @@ public class Table implements Serializable {
113115 /**
114116 * These fields are all cached fields. The information comes from tTable.
115117 */
116- private List <FieldSchema > cachedPartCols ;
118+ private List <FieldSchema > tablePartCols ;
119+ private List <FieldSchema > tableNonPartCols ;
120+ private List <FieldSchema > tableAllCols ;
121+ private Map <String , Pair <Integer , FieldSchema >> inputColumnIndexByName ;
117122 private transient Deserializer deserializer ;
118123 private Class <? extends OutputFormat > outputFormatClass ;
119124 private Class <? extends InputFormat > inputFormatClass ;
@@ -198,8 +203,8 @@ public Table makeCopy() {
198203
199204 newTab .setMetaTable (this .getMetaTable ());
200205 newTab .setSnapshotRef (this .getSnapshotRef ());
201- if (this .cachedPartCols != null ) {
202- newTab .cachedPartCols = new ArrayList <>(this .cachedPartCols );
206+ if (this .tablePartCols != null ) {
207+ newTab .tablePartCols = new ArrayList <>(this .tablePartCols );
203208 }
204209 return newTab ;
205210 }
@@ -616,15 +621,15 @@ private List<FieldSchema> getNativePartCols() {
616621 * where partition columns are not stored in the metastore.
617622 */
618623 public List <FieldSchema > getPartCols () {
619- if (cachedPartCols != null ) {
620- return cachedPartCols ;
624+ if (tablePartCols != null ) {
625+ return tablePartCols ;
621626 }
622627 if (isTableTypeSet () && hasNonNativePartitionSupport ()) {
623- cachedPartCols = getStorageHandler ().getPartitionKeys (this );
628+ tablePartCols = getStorageHandler ().getPartitionKeys (this );
624629 } else {
625- cachedPartCols = getNativePartCols ();
630+ tablePartCols = getNativePartCols ();
626631 }
627- return cachedPartCols ;
632+ return tablePartCols ;
628633 }
629634
630635 private boolean isTableTypeSet () {
@@ -650,7 +655,11 @@ public boolean hasNonNativePartitionSupport() {
650655 }
651656
652657 public boolean isPartitionKey (String colName ) {
653- return getPartColByName (colName ) != null ;
658+ List <FieldSchema > partKeys = getPartitionKeys ();
659+ if (partKeys .isEmpty ()) {
660+ return false ;
661+ }
662+ return partKeys .stream ().map (FieldSchema ::getName ).toList ().contains (colName );
654663 }
655664
656665 // TODO merge this with getBucketCols function
@@ -756,18 +765,48 @@ private boolean isField(String col) {
756765 return false ;
757766 }
758767
759- public List <FieldSchema > getCols () {
768+ private void fillColumnIndexByName () {
769+ inputColumnIndexByName = new HashMap <>();
770+ List <FieldSchema > fsList = new ArrayList <>(getColsInternal (false ));
760771 if (!isNonNative ()) {
761- return getColsInternal (false );
772+ fsList .addAll (getNativePartCols ());
773+ }
774+ for (int i = 0 ; i < fsList .size (); i ++) {
775+ inputColumnIndexByName .put (fsList .get (i ).getName (), Pair .of (i , fsList .get (i )));
776+ }
777+ }
778+
779+ public int getColumnIndexByName (String colName ) {
780+ if (inputColumnIndexByName == null ) {
781+ fillColumnIndexByName ();
782+ }
783+ return inputColumnIndexByName .get (colName .toLowerCase ()).getLeft ();
784+ }
785+
786+ public FieldSchema getFieldSchemaByName (String colName ) {
787+ if (inputColumnIndexByName == null ) {
788+ fillColumnIndexByName ();
762789 }
763- List <FieldSchema > nonPartFields = new ArrayList <>();
764- Set <String > partFieldsName = getPartCols ().stream ().map (FieldSchema ::getName ).collect (Collectors .toSet ());
765- for (FieldSchema field : getColsInternal (false )) {
766- if (!partFieldsName .contains (field .getName ())) {
767- nonPartFields .add (field );
790+ return inputColumnIndexByName .get (colName ).getRight ();
791+ }
792+
793+ public List <FieldSchema > getCols () {
794+ if (tableNonPartCols != null ) {
795+ return tableNonPartCols ;
796+ }
797+ if (!isNonNative ()) {
798+ tableNonPartCols = getColsInternal (false );
799+ } else {
800+ List <FieldSchema > nonPartFields = new ArrayList <>();
801+ Set <String > partFieldsName = getPartCols ().stream ().map (FieldSchema ::getName ).collect (Collectors .toSet ());
802+ for (FieldSchema field : getColsInternal (false )) {
803+ if (!partFieldsName .contains (field .getName ())) {
804+ nonPartFields .add (field );
805+ }
768806 }
807+ tableNonPartCols = nonPartFields ;
769808 }
770- return nonPartFields ;
809+ return tableNonPartCols ;
771810 }
772811
773812 public List <FieldSchema > getColsForMetastore () {
@@ -800,9 +839,18 @@ private List<FieldSchema> getColsInternal(boolean forMs) {
800839 * @return List<FieldSchema>
801840 */
802841 public List <FieldSchema > getAllCols () {
803- ArrayList <FieldSchema > allCols = new ArrayList <>(getCols ());
804- allCols .addAll (getPartCols ());
805- return allCols ;
842+ if (tableAllCols != null ) {
843+ return tableAllCols ;
844+ }
845+ if (inputColumnIndexByName == null ) {
846+ fillColumnIndexByName ();
847+ }
848+ TreeMap <Integer , FieldSchema > orderedMap = new TreeMap <>();
849+ for (Map .Entry <String , Pair <Integer , FieldSchema >> e : inputColumnIndexByName .entrySet ()) {
850+ orderedMap .put (e .getValue ().getLeft (), e .getValue ().getRight ());
851+ }
852+ tableAllCols = orderedMap .values ().stream ().toList ();
853+ return tableAllCols ;
806854 }
807855
808856 public void setPartCols (List <FieldSchema > partCols ) {
0 commit comments