-
Notifications
You must be signed in to change notification settings - Fork 619
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add an ability to read metadata for attached databases #829
base: master
Are you sure you want to change the base?
feat: Add an ability to read metadata for attached databases #829
Conversation
Hi, i don't think we should add a pragma for that. The JDBC methods accept a schema, and if it is |
Hi, pragma is used only for getSchemas to mark if we read them at all. Other parts just check for null. |
i don't think the switch is necessary, we can always retrieve them all |
@gotson I have removed pragma now the schema read is by default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i did a very quick first review
Code formatting is failing, can you run |
5e41cc5
to
4820bfd
Compare
Hi, I Added 2 test cases for the default DB and for attaching an additional one after |
4820bfd
to
6e59227
Compare
.append(quote(s == null ? "main" : s)) | ||
.append(" as TABLE_SCHEM, tblname as TABLE_NAME, ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about that.
The function should return the actual schema of the table, no? But it seems we just feed back the parameter that was passed.
If we have 2 tables with the same name in 2 different schemas, and we call this function without specifying the schema s
, then that function should return columns from both tables, but we would need to have TABLE_SCHEM
to differentiate them.
@@ -1198,7 +1206,9 @@ public ResultSet getPrimaryKeys(String c, String s, String table) throws SQLExce | |||
|
|||
Statement stat = conn.createStatement(); | |||
StringBuilder sql = new StringBuilder(512); | |||
sql.append("select null as TABLE_CAT, ").append(quote(s)).append(" as TABLE_SCHEM, '") | |||
sql.append("select null as TABLE_CAT, ") | |||
.append(quote(s == null ? "main" : s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
@@ -1249,7 +1259,7 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) | |||
|
|||
catalog = (catalog != null) ? quote(catalog) : null; | |||
|
|||
String quotedSchema = (schema != null) ? quote(schema) : null; | |||
String quotedSchema = (schema != null) ? quote(schema) : quote("main"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
@@ -1406,12 +1416,12 @@ public ResultSet getImportedKeys(String catalog, String schema, String table) | |||
sql.append("select ") | |||
.append(quote(catalog)) | |||
.append(" as PKTABLE_CAT, ") | |||
.append(quote(schema)) | |||
.append(quote(schema == null ? "main" : schema)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
.append(" as PKTABLE_SCHEM, ") | ||
.append("ptn as PKTABLE_NAME, pcn as PKCOLUMN_NAME, ") | ||
.append(quote(catalog)) | ||
.append(" as FKTABLE_CAT, ") | ||
.append(quote(schema)) | ||
.append(quote(schema == null ? "main" : schema)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
@@ -1526,7 +1536,7 @@ public ResultSet getIndexInfo(String c, String s, String table, boolean u, boole | |||
// define the column header | |||
// this is from the JDBC spec, it is part of the driver protocol | |||
sql.append("select null as TABLE_CAT,") | |||
.append(quote(s)) | |||
.append(quote(s == null ? "main" : s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
@@ -1689,7 +1705,10 @@ public synchronized ResultSet getTables( | |||
StringBuilder sql = new StringBuilder(); | |||
sql.append("SELECT").append("\n"); | |||
sql.append(" NULL AS TABLE_CAT,").append("\n"); | |||
sql.append(" NULL AS TABLE_SCHEM,").append("\n"); | |||
sql.append(" ") | |||
.append(quote(s == null ? "main" : s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as above, we should return the actual schema of the retrieved PK's table, not the parameter that was passed to the function
I think the logic should be enhance to retrieve various entities. The way the
For all those functions, we probably need to apply that logic:
That means we need to change the logic for all those functions to loop through all known schemas, optionnaly filtered by the |
@gotson Ok, this one looks doable and will probably, be ready sometime next week. |
@gotson Hi, sorry for waiting; unfortunately, I had no time to finish the pr before. I have a question. JDBC has some functions like getExportedKeys that require using full schema name and returns everything if null. Do we want to read the data from all existing schemas or to use old behaviour? |
Added schema(String, String) for pattern matching, which still requires some unit tests and discussion. |
5b4b2ad
to
e5e4f1d
Compare
Also, what should I do with GLOBAL TEMPORARY tables? They kind of have their scheme now. |
@gotson, Hi, again, can we discuss acceptance criteria regarding this pr? Currently, it needs to add some unit tests, and we can probably discuss if anything else is required. Also it looks like this one leads to the significant change of default behaviour, so it probably may require more accurate handling. |
Hi, unit tests would be needed yes. What kind of significant changes of default behavior would you foresee though ? |
@gotson Well, there are some. Most importantly, if the value of the schema pattern is null, it will show all DBs instead of only 'main', that may look like a significant API change. |
It's fine, it is more correct |
…nto add_metadata_read_for_attached_db � Conflicts: � src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java � src/test/java/org/sqlite/DBMetaDataTest.java
@gotson Sorry, could you look at the current state of pr and see if anything else is required? |
469887c
to
61f5344
Compare
The PR has conflict, you would need to fix those before I can have a look. |
@gotson I resolved the conflict with the recent two commits |
Thank you. I don't have much time these days, but I will look at this when I have time. |
I still see conflicts though. Are you sure you pushed your latest changes? |
code formatting is failing, can you fix it with |
@gotson Fixed |
@gotson Hi there! I hope you're doing well. I wanted to reach out and kindly ask if you had a chance to review the pull request. |
It's on my list, unfortunately time is scarce these days. Hopefully i have some time this week to look at it! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this review i mostly focused on the test class. I think we should have more coverage on dynamic attachment, ie for all functions:
- test the behaviour
- attach 1 db
- test the behaviour
- detach the db
- test the behaviour
Is that something you could add ?
// assertThat(rs.next()).isTrue(); | ||
// assertThat(rs.getString("TABLE_NAME")).isEqualTo("sqlite_schema"); | ||
// assertThat(rs.getString("TABLE_SCHEM")).isEqualTo("temp"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's with those commented lines?
} | ||
} | ||
|
||
private void assertSystemSchema(ResultSet rs) throws SQLException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't that also check for TABLE_SCHEM
and compare it to a parameter passed in the function?
// SYSTEM TABLE "sqlite_schema" for main | ||
assertSystemSchema(rs); | ||
|
||
// SYSTEM TABLE "sqlite_schema" for temp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where is that temp
database attached? i can't find any mention to it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
temp is for the sqlite temporary files, I think are returned as system external schema if any exist.
@@ -1001,7 +999,7 @@ public void columnOrderOfgetTables() throws SQLException { | |||
ResultSet rsTables = | |||
meta.getTables( | |||
null, | |||
null, | |||
"", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about that, i don't think passing ""
should match any schema, that's what passing null
is for.
@@ -1158,7 +1156,7 @@ public void columnOrderOfgetProcedurColumns() throws SQLException { | |||
@Test | |||
public void columnOrderOfgetSchemas() throws SQLException { | |||
ResultSet rs = meta.getSchemas(); | |||
assertThat(rs.next()).isFalse(); | |||
assertThat(rs.next()).isTrue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we have more assertions to verify the content of the result set?
rs = meta.getTables(null, "main", null, new String[] {"table"}); | ||
assertThat(rs.next()).isTrue(); | ||
assertThat(rs.getString("TABLE_NAME")).isEqualTo("test"); | ||
assertThat(rs.next()).isFalse(); | ||
rs.close(); | ||
|
||
rs = meta.getTables(null, "main", null, new String[] {"view"}); | ||
assertThat(rs.next()).isTrue(); | ||
assertThat(rs.getString("TABLE_NAME")).isEqualTo("testView"); | ||
assertThat(rs.next()).isFalse(); | ||
rs.close(); | ||
|
||
rs = meta.getTables(null, "main", null, new String[] {"system table"}); | ||
assertThat(rs.next()).isTrue(); | ||
assertThat(rs.getString("TABLE_NAME")).isEqualTo("sqlite_schema"); | ||
assertThat(rs.next()).isFalse(); | ||
rs.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we have the same suite of tests for db2
for consistency?
boolean schemaFound = false; | ||
while (schemas.next()) { | ||
schemaFound = "db3".equals(schemas.getString("TABLE_SCHEM")); | ||
if (schemaFound) { | ||
break; | ||
} | ||
} | ||
assertThat(schemaFound).isTrue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe put all schemas in a list and verify that it contains all the values we expect, ie db2
,db3
and main
.
If we expect some ordering, we should also test for that here.
} | ||
|
||
@Test | ||
public void testGetSchemasForAttachedDatabases() throws SQLException, IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the above function name implies it's about dynamic attachment, but this one doesn't
assertThat(schemaFound).isTrue(); | ||
|
||
} finally { | ||
stat.executeUpdate("detach database db3;"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also test after the detach that the schemas are properly returned?
if ("".equals(schemaPattern)) { | ||
schemaPattern = "main"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should have that behaviour. The documentation says:
schemaPattern – a schema name; must match the schema name as it is stored in the database; null means schema name should not be used to narrow down the search.
There is no mention of a special handling when passing ""
Hi SQLite team!
Here are my proposed changes to the reading of metadata. To allow to read of metadata from attached databases
https://www.sqlite.org/lang_attach.html
This functionality will be optional and disabled by default because it adds more layers[schema].[table]
for metadata reading.The reason why this functionality will be useful:
It isn't easy to work with attached databases using JDBC API because all metadata reading assumes that we are in the main schema. This is fixable by adding schema information to the existing queries.