Skip to content

Commit 004f828

Browse files
refactor(schema): add database filtering to JSON detection
Updated `detectMariaDBJSON` to accept `dbName` as a parameter, enabling filtering by `CONSTRAINT_SCHEMA` for more precise JSON constraint detection within specified databases.
1 parent d498902 commit 004f828

File tree

1 file changed

+45
-44
lines changed

1 file changed

+45
-44
lines changed

src/main/java/com/zendesk/maxwell/schema/SchemaCapturer.java

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public class SchemaCapturer implements AutoCloseable {
2424
static final Logger LOGGER = LoggerFactory.getLogger(SchemaCapturer.class);
2525

2626
public static final HashSet<String> IGNORED_DATABASES = new HashSet<>(
27-
Arrays.asList(new String[]{"performance_schema", "information_schema"})
28-
);
27+
Arrays.asList(new String[] { "performance_schema", "information_schema" }));
2928

3029
private final Set<String> includeDatabases;
3130
private final Set<String> includeTables;
@@ -36,12 +35,12 @@ public class SchemaCapturer implements AutoCloseable {
3635
private final PreparedStatement columnPreparedStatement;
3736
private final PreparedStatement pkPreparedStatement;
3837

39-
4038
public SchemaCapturer(Connection c, CaseSensitivity sensitivity) throws SQLException {
4139
this(c, sensitivity, Collections.emptySet(), Collections.emptySet());
4240
}
4341

44-
SchemaCapturer(Connection c, CaseSensitivity sensitivity, Set<String> includeDatabases, Set<String> includeTables) throws SQLException {
42+
SchemaCapturer(Connection c, CaseSensitivity sensitivity, Set<String> includeDatabases, Set<String> includeTables)
43+
throws SQLException {
4544
this.includeDatabases = includeDatabases;
4645
this.includeTables = includeTables;
4746
this.connection = c;
@@ -99,12 +98,10 @@ public Schema capture() throws SQLException {
9998
LOGGER.debug("Capturing schemas...");
10099
ArrayList<Database> databases = new ArrayList<>();
101100

102-
String dbCaptureQuery =
103-
"SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA";
101+
String dbCaptureQuery = "SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.SCHEMATA";
104102

105-
if ( includeDatabases.size() > 0 ) {
106-
dbCaptureQuery +=
107-
" WHERE SCHEMA_NAME IN " + Sql.inListSQL(includeDatabases.size());
103+
if (includeDatabases.size() > 0) {
104+
dbCaptureQuery += " WHERE SCHEMA_NAME IN " + Sql.inListSQL(includeDatabases.size());
108105
}
109106
dbCaptureQuery += " ORDER BY SCHEMA_NAME";
110107

@@ -135,13 +132,14 @@ public Schema capture() throws SQLException {
135132
}
136133
LOGGER.debug("{} database schemas captured!", size);
137134

138-
139135
Schema s = new Schema(databases, captureDefaultCharset(), this.sensitivity);
140136
try {
141-
if ( isMariaDB() && mariaSupportsJSON()) {
142-
detectMariaDBJSON(s);
137+
if (isMariaDB() && mariaSupportsJSON()) {
138+
for (String dbName : s.getDatabaseNames()) {
139+
detectMariaDBJSON(s, dbName);
140+
}
143141
}
144-
} catch ( InvalidSchemaError e ) {
142+
} catch (InvalidSchemaError e) {
145143
e.printStackTrace();
146144
}
147145
return s;
@@ -150,13 +148,12 @@ public Schema capture() throws SQLException {
150148
private String captureDefaultCharset() throws SQLException {
151149
LOGGER.debug("Capturing Default Charset");
152150
try (Statement stmt = connection.createStatement();
153-
ResultSet rs = stmt.executeQuery("select @@character_set_server")) {
151+
ResultSet rs = stmt.executeQuery("select @@character_set_server")) {
154152
rs.next();
155153
return rs.getString("@@character_set_server");
156154
}
157155
}
158156

159-
160157
private void captureDatabase(Database db) throws SQLException {
161158
tablePreparedStatement.setString(1, db.getName());
162159
Sql.prepareInList(tablePreparedStatement, 2, includeTables);
@@ -173,9 +170,8 @@ private void captureDatabase(Database db) throws SQLException {
173170
captureTables(db, tables);
174171
}
175172

176-
177173
private boolean isMySQLAtLeast56() throws SQLException {
178-
if ( isMariaDB() )
174+
if (isMariaDB())
179175
return true;
180176

181177
DatabaseMetaData meta = connection.getMetaData();
@@ -190,13 +186,14 @@ private boolean isMariaDB() throws SQLException {
190186
}
191187

192188
static final String MARIA_VERSION_REGEX = "[\\d\\.]+-(\\d+)\\.(\\d+)";
189+
193190
private boolean mariaSupportsJSON() throws SQLException {
194191
DatabaseMetaData meta = connection.getMetaData();
195192
String versionString = meta.getDatabaseProductVersion();
196193
Pattern pattern = Pattern.compile(MARIA_VERSION_REGEX);
197194
Matcher m = pattern.matcher(versionString);
198195

199-
if ( m.find() ) {
196+
if (m.find()) {
200197
int major = Integer.parseInt(m.group(1));
201198
int minor = Integer.parseInt(m.group(2));
202199

@@ -267,7 +264,7 @@ private void captureTablesPK(Database db, HashMap<String, Table> tables) throws
267264
String columnName = rs.getString("COLUMN_NAME");
268265

269266
ArrayList<String> pkList = tablePKMap.get(tableName);
270-
if ( pkList != null )
267+
if (pkList != null)
271268
pkList.add(ordinalPosition - 1, columnName);
272269
}
273270
}
@@ -294,7 +291,7 @@ static String[] extractEnumValues(String expandedType) {
294291
Matcher enumMatcher = pattern.matcher(enumValues);
295292

296293
List<String> result = new ArrayList<>();
297-
while(enumMatcher.find()) {
294+
while (enumMatcher.find()) {
298295
String value = enumMatcher.group(0);
299296
if (value.startsWith("'"))
300297
value = value.substring(1);
@@ -309,44 +306,48 @@ static String[] extractEnumValues(String expandedType) {
309306
@Override
310307
public void close() throws SQLException {
311308
try (PreparedStatement p1 = tablePreparedStatement;
312-
PreparedStatement p2 = columnPreparedStatement;
313-
PreparedStatement p3 = pkPreparedStatement) {
309+
PreparedStatement p2 = columnPreparedStatement;
310+
PreparedStatement p3 = pkPreparedStatement) {
314311
// auto-close shared prepared statements
315312
}
316313
}
317314

318-
private void detectMariaDBJSON(Schema schema) throws SQLException, InvalidSchemaError {
315+
private void detectMariaDBJSON(Schema schema, String dbName) throws SQLException, InvalidSchemaError {
319316
String checkConstraintSQL = "SELECT CONSTRAINT_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, CHECK_CLAUSE " +
320-
"from INFORMATION_SCHEMA.CHECK_CONSTRAINTS " +
321-
"where CHECK_CLAUSE LIKE 'json_valid(%)'";
317+
"from INFORMATION_SCHEMA.CHECK_CONSTRAINTS " +
318+
"where CONSTRAINT_SCHEMA = ? AND CHECK_CLAUSE LIKE 'json_valid(%)'";
322319

323320
String regex = "json_valid\\(`(.*)`\\)";
324321
Pattern pattern = Pattern.compile(regex);
325322

326323
try (
327-
PreparedStatement statement = connection.prepareStatement(checkConstraintSQL);
328-
ResultSet rs = statement.executeQuery()
329-
) {
330-
while ( rs.next() ) {
331-
String checkClause = rs.getString("CHECK_CLAUSE");
332-
Matcher m = pattern.matcher(checkClause);
333-
if ( m.find() ) {
334-
String column = m.group(1);
335-
Database d = schema.findDatabase(rs.getString("CONSTRAINT_SCHEMA"));
336-
if ( d == null ) continue;
337-
Table t = d.findTable(rs.getString("TABLE_NAME"));
338-
if ( t == null ) continue;
339-
short i = t.findColumnIndex(column);
340-
if ( i < 0 ) continue;
341-
342-
ColumnDef cd = t.findColumn(i);
343-
if ( cd instanceof StringColumnDef ) {
344-
t.replaceColumn(i, JsonColumnDef.create(cd.getName(), "json", i));
324+
PreparedStatement statement = connection.prepareStatement(checkConstraintSQL)) {
325+
statement.setString(1, dbName);
326+
327+
try (ResultSet rs = statement.executeQuery()) {
328+
while (rs.next()) {
329+
String checkClause = rs.getString("CHECK_CLAUSE");
330+
Matcher m = pattern.matcher(checkClause);
331+
if (m.find()) {
332+
String column = m.group(1);
333+
Database d = schema.findDatabase(rs.getString("CONSTRAINT_SCHEMA"));
334+
if (d == null)
335+
continue;
336+
Table t = d.findTable(rs.getString("TABLE_NAME"));
337+
if (t == null)
338+
continue;
339+
short i = t.findColumnIndex(column);
340+
if (i < 0)
341+
continue;
342+
343+
ColumnDef cd = t.findColumn(i);
344+
if (cd instanceof StringColumnDef) {
345+
t.replaceColumn(i, JsonColumnDef.create(cd.getName(), "json", i));
346+
}
345347
}
346348
}
347349
}
348350
}
349-
350351
}
351352

352353
}

0 commit comments

Comments
 (0)