2929import java .sql .SQLException ;
3030import java .text .DecimalFormat ;
3131import java .text .NumberFormat ;
32+ import java .util .ArrayList ;
3233import java .util .Arrays ;
3334import java .util .Base64 ;
35+ import java .util .HashMap ;
3436import java .util .Iterator ;
37+ import java .util .List ;
38+ import java .util .Map ;
3539
3640import org .apache .hadoop .hive .common .cli .EscapeCRLFHelper ;
3741
4246abstract class Rows implements Iterator {
4347 protected final BeeLine beeLine ;
4448 final ResultSetMetaData rsMeta ;
45- final Boolean [] primaryKeys ;
49+ final boolean [] primaryKeyColumns ;
50+ boolean isPrimaryKeyColumnsInitialized ;
4651 final NumberFormat numberFormat ;
4752 private boolean convertBinaryArrayToString ;
4853 private final String nullStr ;
@@ -51,14 +56,15 @@ abstract class Rows implements Iterator {
5156 this .beeLine = beeLine ;
5257 nullStr = beeLine .getOpts ().getNullString ();
5358 rsMeta = rs .getMetaData ();
54- int count = rsMeta .getColumnCount ();
55- primaryKeys = new Boolean [count ];
5659 if (beeLine .getOpts ().getNumberFormat ().equals ("default" )) {
5760 numberFormat = null ;
5861 } else {
5962 numberFormat = new DecimalFormat (beeLine .getOpts ().getNumberFormat ());
6063 }
6164 this .convertBinaryArrayToString = beeLine .getOpts ().getConvertBinaryArrayToString ();
65+
66+ int count = this .rsMeta .getColumnCount ();
67+ primaryKeyColumns = new boolean [count ];
6268 }
6369
6470 @ Override
@@ -78,37 +84,47 @@ public void remove() {
7884 * JDBC driver property implements {@link ResultSetMetaData#getTableName} (many do not), it
7985 * is not reliable for all databases.
8086 */
81- boolean isPrimaryKey (int col ) {
82- if (primaryKeys [col ] == null ) {
83- try {
84- // this doesn't always work, since some JDBC drivers (e.g.,
85- // Oracle's) return a blank string from getDbTableName.
86- String table = rsMeta .getTableName (col + 1 );
87- String column = rsMeta .getColumnName (col + 1 );
87+ boolean isPrimaryKeyCol (int col ) {
88+ if (!isPrimaryKeyColumnsInitialized ) {
89+ initializePrimaryKeyMetadata ();
90+ }
91+
92+ return primaryKeyColumns [col ];
93+ }
94+
95+ private void initializePrimaryKeyMetadata () {
96+ Map <String , List <String >> tablePrimaryKeys = new HashMap <>();
97+
98+ try {
99+ for (int i = 0 ; i < primaryKeyColumns .length ; i ++) {
100+ String table = rsMeta .getTableName (i + 1 );
101+ String column = rsMeta .getColumnName (i + 1 );
88102
89103 if (table == null || table .isEmpty () || column == null || column .isEmpty ()) {
90- primaryKeys [col ] = Boolean .FALSE ;
91- } else {
92- ResultSet pks = beeLine .getDatabaseConnection ().getDatabaseMetaData ().getPrimaryKeys (
93- beeLine .getDatabaseConnection ().getDatabaseMetaData ().getConnection ().getCatalog (), null , table );
104+ continue ;
105+ }
106+
107+ if (!tablePrimaryKeys .containsKey (table )) {
108+ try (ResultSet pks = beeLine .getDatabaseConnection ().getDatabaseMetaData ().getPrimaryKeys (
109+ beeLine .getDatabaseConnection ().getDatabaseMetaData ().getConnection ().getCatalog (), null , table )) {
110+
111+ List <String > pkNames = new ArrayList <>();
94112
95- primaryKeys [col ] = Boolean .FALSE ;
96- try {
97113 while (pks .next ()) {
98- if (column .equalsIgnoreCase (pks .getString ("COLUMN_NAME" ))) {
99- primaryKeys [col ] = Boolean .TRUE ;
100- break ;
101- }
114+ pkNames .add (pks .getString ("COLUMN_NAME" ));
102115 }
103- } finally {
104- pks . close ( );
116+
117+ tablePrimaryKeys . put ( table , pkNames );
105118 }
106119 }
107- } catch ( SQLException sqle ) {
108- primaryKeys [ col ] = Boolean . FALSE ;
120+
121+ primaryKeyColumns [ i ] = tablePrimaryKeys . get ( table ). contains ( column ) ;
109122 }
123+ } catch (SQLException e ) {
124+ // Do nothing. We cannot decide if the given column is a primary key so we keep it as false
110125 }
111- return primaryKeys [col ].booleanValue ();
126+
127+ isPrimaryKeyColumnsInitialized = true ;
112128 }
113129
114130 class Row {
@@ -134,7 +150,7 @@ class Row {
134150 }
135151
136152 @ Override
137- public String toString (){
153+ public String toString () {
138154 return Arrays .asList (values ).toString ();
139155 }
140156
@@ -156,17 +172,17 @@ public String toString(){
156172 } catch (Throwable t ) {
157173 }
158174
159- for (int i = 0 ; i < size ; i ++) {
175+ for (int i = 0 ; i < size ; i ++) {
160176 Object o = rs .getObject (i + 1 );
161177 String value = null ;
162178
163179 if (o == null ) {
164180 value = nullStr ;
165181 } else if (o instanceof Number ) {
166182 value = numberFormat != null ? numberFormat .format (o ) :
167- o instanceof BigDecimal ? ((BigDecimal )o ).toPlainString () : o .toString ();
183+ o instanceof BigDecimal ? ((BigDecimal ) o ).toPlainString () : o .toString ();
168184 } else if (o instanceof byte []) {
169- value = convertBinaryArrayToString ? new String ((byte [])o , StandardCharsets .UTF_8 ) : Base64 .getEncoder ().withoutPadding ().encodeToString ((byte [])o );
185+ value = convertBinaryArrayToString ? new String ((byte []) o , StandardCharsets .UTF_8 ) : Base64 .getEncoder ().withoutPadding ().encodeToString ((byte []) o );
170186 } else {
171187 value = rs .getString (i + 1 );
172188 }
0 commit comments