Skip to content

Commit e46b0fd

Browse files
committed
dialect adapter changes
1 parent e83ef1d commit e46b0fd

4 files changed

Lines changed: 115 additions & 0 deletions

File tree

v2/sourcedb-to-spanner/src/main/java/com/google/cloud/teleport/v2/source/reader/io/jdbc/dialectadapter/mysql/MysqlDialectAdapter.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,24 @@ public boolean checkForTimeout(SQLException exception) {
727727
return false;
728728
}
729729

730+
@Override
731+
public boolean supportsApproximateCounts() {
732+
return true;
733+
}
734+
735+
@Override
736+
public String getApproximateCountQuery(String tableName, ImmutableList<String> partitionColumns) {
737+
return addWhereClause("EXPLAIN SELECT * FROM " + tableName, partitionColumns);
738+
}
739+
740+
@Override
741+
public long parseApproximateCount(ResultSet rs) throws SQLException {
742+
if (rs.next()) {
743+
return rs.getLong("rows");
744+
}
745+
return -1L;
746+
}
747+
730748
/**
731749
* Get Query that returns order of collation. The query must return all the characters in the
732750
* character set with the columns listed in {@link CollationsOrderQueryColumns}.

v2/sourcedb-to-spanner/src/main/java/com/google/cloud/teleport/v2/source/reader/io/jdbc/dialectadapter/postgresql/PostgreSQLDialectAdapter.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,30 @@ public boolean checkForTimeout(SQLException exception) {
533533
&& TIMEOUT_SQL_STATES.contains(exception.getSQLState().toUpperCase());
534534
}
535535

536+
@Override
537+
public boolean supportsApproximateCounts() {
538+
return true;
539+
}
540+
541+
@Override
542+
public String getApproximateCountQuery(String tableName, ImmutableList<String> partitionColumns) {
543+
return addWhereClause("EXPLAIN SELECT * FROM " + tableName, partitionColumns);
544+
}
545+
546+
@Override
547+
public long parseApproximateCount(ResultSet rs) throws SQLException {
548+
if (rs.next()) {
549+
String explainPlan = rs.getString(1);
550+
// PostgreSQL default EXPLAIN format contains "rows=N"
551+
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("rows=(\\d+)");
552+
java.util.regex.Matcher matcher = pattern.matcher(explainPlan);
553+
if (matcher.find()) {
554+
return Long.parseLong(matcher.group(1));
555+
}
556+
}
557+
return -1L;
558+
}
559+
536560
/**
537561
* Ref <a href="https://www.db-fiddle.com/f/sJyGyFpqfnoxYFpEXPxR1/0"></a> Get Query that returns
538562
* order of collation. The query must return all the characters in the character set with the

v2/sourcedb-to-spanner/src/test/java/com/google/cloud/teleport/v2/source/reader/io/jdbc/dialectadapter/mysql/MysqlDialectAdapterTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,40 @@ public void testExtractBoundaryDuration() throws Exception {
889889
.isEqualTo(java.time.Duration.ofHours(-838).minusMinutes(59).minusSeconds(59));
890890
}
891891

892+
@Test
893+
public void testSupportsApproximateCounts() {
894+
assertThat(new MysqlDialectAdapter(MySqlVersion.DEFAULT).supportsApproximateCounts()).isTrue();
895+
}
896+
897+
@Test
898+
public void testGetApproximateCountQuery() {
899+
String testTable = "testTable";
900+
ImmutableList<String> cols = ImmutableList.of("col_1", "col_2");
901+
String query =
902+
new MysqlDialectAdapter(MySqlVersion.DEFAULT).getApproximateCountQuery(testTable, cols);
903+
assertThat(query).contains("EXPLAIN SELECT * FROM testTable");
904+
assertThat(query).contains("col_1");
905+
assertThat(query).contains("col_2");
906+
}
907+
908+
@Test
909+
public void testParseApproximateCount() throws SQLException {
910+
ResultSet mockResultSet = mock(ResultSet.class);
911+
when(mockResultSet.next()).thenReturn(true);
912+
when(mockResultSet.getLong("rows")).thenReturn(1234L);
913+
assertThat(new MysqlDialectAdapter(MySqlVersion.DEFAULT).parseApproximateCount(mockResultSet))
914+
.isEqualTo(1234L);
915+
}
916+
917+
@Test
918+
public void testParseApproximateCount_emptyResultSet() throws SQLException {
919+
ResultSet mockResultSet = mock(ResultSet.class);
920+
when(mockResultSet.next()).thenReturn(false);
921+
assertThat(new MysqlDialectAdapter(MySqlVersion.DEFAULT).parseApproximateCount(mockResultSet))
922+
.isEqualTo(-1L);
923+
}
924+
925+
@Test
892926
public void testGetCollationsOrderQuery() {
893927
MysqlDialectAdapter adapter = new MysqlDialectAdapter(MySqlVersion.DEFAULT);
894928
String dbCharset = "utf8mb4";

v2/sourcedb-to-spanner/src/test/java/com/google/cloud/teleport/v2/source/reader/io/jdbc/dialectadapter/postgresql/PostgreSQLDialectAdapterTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static com.google.common.truth.Truth.assertThat;
1919
import static org.junit.Assert.assertThrows;
2020
import static org.mockito.ArgumentMatchers.anyString;
21+
import static org.mockito.Mockito.mock;
2122
import static org.mockito.Mockito.when;
2223

2324
import com.google.cloud.teleport.v2.source.reader.io.exception.RetriableSchemaDiscoveryException;
@@ -597,4 +598,42 @@ public void testDiscoverTableIndexes_skipsExtraTables()
597598
assertThat(result).containsKey(table1);
598599
assertThat(result).doesNotContainKey(extraTable);
599600
}
601+
602+
@Test
603+
public void testSupportsApproximateCounts() {
604+
assertThat(adapter.supportsApproximateCounts()).isTrue();
605+
}
606+
607+
@Test
608+
public void testGetApproximateCountQuery() {
609+
String tableName = "testTable";
610+
ImmutableList<String> partitionColumns = ImmutableList.of("col1", "col2");
611+
String query = adapter.getApproximateCountQuery(tableName, partitionColumns);
612+
assertThat(query).contains("EXPLAIN SELECT * FROM testTable");
613+
assertThat(query).contains("col1");
614+
assertThat(query).contains("col2");
615+
}
616+
617+
@Test
618+
public void testParseApproximateCount() throws SQLException {
619+
ResultSet mockRs = mock(ResultSet.class);
620+
when(mockRs.next()).thenReturn(true);
621+
when(mockRs.getString(1)).thenReturn("Seq Scan on testTable (cost=0.00..1.01 rows=42 width=4)");
622+
assertThat(adapter.parseApproximateCount(mockRs)).isEqualTo(42L);
623+
}
624+
625+
@Test
626+
public void testParseApproximateCount_emptyResultSet() throws SQLException {
627+
ResultSet mockRs = mock(ResultSet.class);
628+
when(mockRs.next()).thenReturn(false);
629+
assertThat(adapter.parseApproximateCount(mockRs)).isEqualTo(-1L);
630+
}
631+
632+
@Test
633+
public void testParseApproximateCount_parsingFailure() throws SQLException {
634+
ResultSet mockRs = mock(ResultSet.class);
635+
when(mockRs.next()).thenReturn(true);
636+
when(mockRs.getString(1)).thenReturn("Some unrecognized output");
637+
assertThat(adapter.parseApproximateCount(mockRs)).isEqualTo(-1L);
638+
}
600639
}

0 commit comments

Comments
 (0)