diff --git a/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java b/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java
index d764b152..7074b0ca 100644
--- a/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java
+++ b/src/main/java/org/duckdb/DuckDBDatabaseMetaData.java
@@ -18,6 +18,7 @@
import javax.sql.rowset.RowSetProvider;
public class DuckDBDatabaseMetaData implements DatabaseMetaData {
+
DuckDBConnection conn;
public DuckDBDatabaseMetaData(DuckDBConnection conn) {
@@ -170,27 +171,74 @@ public String getIdentifierQuoteString() throws SQLException {
@Override
public String getSQLKeywords() throws SQLException {
- throw new SQLFeatureNotSupportedException("getSQLKeywords");
+ Statement statement = conn.createStatement();
+ statement.closeOnCompletion();
+ ResultSet rs = statement.executeQuery("SELECT keyword_name FROM duckdb_keywords()");
+ StringBuilder sb = new StringBuilder();
+ while (rs.next()) {
+ sb.append(rs.getString(1));
+ sb.append(',');
+ }
+ return sb.toString();
}
@Override
public String getNumericFunctions() throws SQLException {
- throw new SQLFeatureNotSupportedException("getNumericFunctions");
+ Statement statement = conn.createStatement();
+ statement.closeOnCompletion();
+ ResultSet rs = statement.executeQuery("SELECT DISTINCT function_name FROM duckdb_functions() "
+ + "WHERE parameter_types[1] ='DECIMAL'"
+ + "OR parameter_types[1] ='DOUBLE'"
+ + "OR parameter_types[1] ='SMALLINT'"
+ + "OR parameter_types[1] = 'BIGINT'");
+ StringBuilder sb = new StringBuilder();
+ while (rs.next()) {
+ sb.append(rs.getString(1));
+ sb.append(',');
+ }
+ return sb.toString();
}
@Override
public String getStringFunctions() throws SQLException {
- throw new SQLFeatureNotSupportedException("getStringFunctions");
+ Statement statement = conn.createStatement();
+ statement.closeOnCompletion();
+ ResultSet rs = statement.executeQuery(
+ "SELECT DISTINCT function_name FROM duckdb_functions() WHERE parameter_types[1] = 'VARCHAR'");
+ StringBuilder sb = new StringBuilder();
+ while (rs.next()) {
+ sb.append(rs.getString(1));
+ sb.append(',');
+ }
+ return sb.toString();
}
@Override
public String getSystemFunctions() throws SQLException {
- throw new SQLFeatureNotSupportedException("getSystemFunctions");
+ Statement statement = conn.createStatement();
+ statement.closeOnCompletion();
+ ResultSet rs = statement.executeQuery(
+ "SELECT DISTINCT function_name FROM duckdb_functions() WHERE length(parameter_types) = 0");
+ StringBuilder sb = new StringBuilder();
+ while (rs.next()) {
+ sb.append(rs.getString(1));
+ sb.append(',');
+ }
+ return sb.toString();
}
@Override
public String getTimeDateFunctions() throws SQLException {
- throw new SQLFeatureNotSupportedException("getTimeDateFunctions");
+ Statement statement = conn.createStatement();
+ statement.closeOnCompletion();
+ ResultSet rs = statement.executeQuery(
+ "SELECT DISTINCT function_name FROM duckdb_functions() WHERE parameter_types[1] LIKE 'TIME%'");
+ StringBuilder sb = new StringBuilder();
+ while (rs.next()) {
+ sb.append(rs.getString(1));
+ sb.append(',');
+ }
+ return sb.toString();
}
@Override
@@ -730,14 +778,16 @@ public ResultSet getTables(String catalog, String schemaPattern, String tableNam
str.append(", NULL::VARCHAR AS 'REF_GENERATION'").append(lineSeparator());
str.append("FROM information_schema.tables").append(lineSeparator());
- // tableNamePattern - a table name pattern; must match the table name as it is stored in the database
+ // tableNamePattern - a table name pattern; must match the table name as it
+ // is stored in the database
if (tableNamePattern == null) {
// non-standard behavior.
tableNamePattern = "%";
}
str.append("WHERE table_name LIKE ?").append(lineSeparator());
- // catalog - a catalog name; must match the catalog name as it is stored in the database;
+ // catalog - a catalog name; must match the catalog name as it is stored in
+ // the database;
// "" retrieves those without a catalog;
// null means that the catalog name should not be used to narrow the search
boolean hasCatalogParam = false;
@@ -751,7 +801,8 @@ public ResultSet getTables(String catalog, String schemaPattern, String tableNam
}
}
- // schemaPattern - a schema name pattern; must match the schema name as it is stored in the database;
+ // schemaPattern - a schema name pattern; must match the schema name as it
+ // is stored in the database;
// "" retrieves those without a schema;
// null means that the schema name should not be used to narrow the search
boolean hasSchemaParam = false;
@@ -979,7 +1030,43 @@ public ResultSet getTypeInfo() throws SQLException {
@Override
public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
throws SQLException {
- throw new SQLFeatureNotSupportedException("getIndexInfo(");
+ StringBuilder sb = new StringBuilder();
+ sb.append("SELECT database_name AS TABLE_CAT "
+ + ", schema_name AS TABLE_SCHEM "
+ + ", table_name AS TABLE_NAME "
+ + ", index_name AS INDEX_NAME "
+ + ", CASE WHEN is_unique THEN 0 ELSE 1 END AS NON_UNIQUE "
+ + ", NULL AS TYPE "
+ + ", NULL AS ORDINAL_POSITION "
+ + ", NULL AS COLUMN_NAME "
+ + ", NULL AS ASC_OR_DESC "
+ + ", NULL AS CARDINALITY "
+ + ", NULL AS PAGES "
+ + ", NULL AS FILTER_CONDITION "
+ + "FROM duckdb_indexes() WHERE TRUE ");
+ if (catalog != null) {
+ sb.append(" AND database_name = ?");
+ }
+ if (schema != null) {
+ sb.append(" AND schema_name = ?");
+ }
+ if (table != null) {
+ sb.append(" AND table_name = ?");
+ }
+ sb.append(" ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, NON_UNIQUE, INDEX_NAME, ORDINAL_POSITION");
+ PreparedStatement ps = conn.prepareStatement(sb.toString());
+ int paramIndex = 1;
+ if (catalog != null) {
+ ps.setString(paramIndex++, catalog);
+ }
+ if (schema != null) {
+ ps.setString(paramIndex++, schema);
+ }
+ if (table != null) {
+ ps.setString(paramIndex++, table);
+ }
+ ps.closeOnCompletion();
+ return ps.executeQuery();
}
@Override
@@ -1158,25 +1245,26 @@ public ResultSet getClientInfoProperties() throws SQLException {
*
* @param catalog a catalog name; must match the catalog name as it
* is stored in the database; "" retrieves those without a catalog;
- * null
means that the catalog name should not be used to narrow
- * the search
+ * null
means that the catalog name should not be used to
+ * narrow the search
* @param schemaPattern a schema name pattern; must match the schema name
- * as it is stored in the database; "" retrieves those without a schema;
- * null
means that the schema name should not be used to narrow
- * the search
+ * as it is stored in the database; "" retrieves those without a
+ * schema; null
means that the schema name should not be used to
+ * narrow the search
* @param functionNamePattern a function name pattern; must match the
* function name as it is stored in the database
* FUNCTION_CAT String => function catalog (may be null)
* FUNCTION_SCHEM String => function schema (may be null)
- * FUNCTION_NAME String => function name. This is the name used to invoke the function
- * REMARKS String => explanatory comment on the function
+ * FUNCTION_NAME String => function name. This is the name used to invoke the
+ * function REMARKS String => explanatory comment on the function
* FUNCTION_TYPE short => kind of function:
- * - functionResultUnknown - Cannot determine if a return value or table will be returned
+ * - functionResultUnknown - Cannot determine if a return value or table will
+ * be returned
* - functionNoTable- Does not return a table
* - functionReturnsTable - Returns a table
- * SPECIFIC_NAME String => the name which uniquely identifies this function within its schema. This is a user
- * specified, or DBMS generated, name that may be different then the FUNCTION_NAME for example with overload
- * functions
+ * SPECIFIC_NAME String => the name which uniquely identifies this function
+ * within its schema. This is a user specified, or DBMS generated, name that
+ * may be different then the FUNCTION_NAME for example with overload functions
*/
@Override
public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
diff --git a/src/test/java/org/duckdb/TestDuckDBJDBC.java b/src/test/java/org/duckdb/TestDuckDBJDBC.java
index c0fb4737..a68aa984 100644
--- a/src/test/java/org/duckdb/TestDuckDBJDBC.java
+++ b/src/test/java/org/duckdb/TestDuckDBJDBC.java
@@ -4420,6 +4420,80 @@ public static void test_column_metadata() throws Exception {
}
}
+ public static void test_metadata_get_sql_keywords() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ String rs = conn.getMetaData().getSQLKeywords();
+ String[] keywords = rs.split(",");
+ List list = asList(keywords);
+ assertTrue(list.contains("select"));
+ assertTrue(list.contains("update"));
+ assertTrue(list.contains("delete"));
+ assertTrue(list.contains("drop"));
+ }
+ }
+
+ public static void test_metadata_get_numeric_functions() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ String rs = conn.getMetaData().getNumericFunctions();
+ // print out rs
+ String[] functions = rs.split(",");
+ List list = asList(functions);
+ assertTrue(list.contains("abs"));
+ assertTrue(list.contains("ceil"));
+ assertTrue(list.contains("floor"));
+ assertTrue(list.contains("round"));
+ }
+ }
+
+ public static void test_metadata_get_string_functions() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ String rs = conn.getMetaData().getStringFunctions();
+ String[] functions = rs.split(",");
+ List list = asList(functions);
+ assertTrue(list.contains("md5"));
+ assertTrue(list.contains("json_keys"));
+ assertTrue(list.contains("repeat"));
+ assertTrue(list.contains("from_base64"));
+ }
+ }
+
+ public static void test_metadata_get_system_functions() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ String rs = conn.getMetaData().getSystemFunctions();
+ String[] functions = rs.split(",");
+ List list = asList(functions);
+ assertTrue(list.contains("current_date"));
+ assertTrue(list.contains("now"));
+ }
+ }
+
+ public static void test_metadata_get_time_date_functions() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ String rs = conn.getMetaData().getTimeDateFunctions();
+ String[] functions = rs.split(",");
+ List list = asList(functions);
+ assertTrue(list.contains("day"));
+ assertTrue(list.contains("dayname"));
+ assertTrue(list.contains("timezone_hour"));
+ }
+ }
+
+ public static void test_metadata_get_index_info() throws Exception {
+ try (Connection conn = DriverManager.getConnection(JDBC_URL)) {
+ try (Statement stmt = conn.createStatement()) {
+ stmt.execute("CREATE TABLE test (id INT PRIMARY KEY, ok INT)");
+ stmt.execute("CREATE INDEX idx_test_ok ON test(ok)");
+ }
+
+ try (ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "test", false, false)) {
+ assertTrue(rs.next());
+ assertEquals(rs.getString("TABLE_NAME"), "test");
+ assertEquals(rs.getString("INDEX_NAME"), "idx_test_ok");
+ assertEquals(rs.getBoolean("NON_UNIQUE"), true);
+ }
+ }
+ }
+
public static void main(String[] args) throws Exception {
System.exit(runTests(args, TestDuckDBJDBC.class, TestExtensionTypes.class));
}
diff --git a/src/test/test.iml b/src/test/test.iml
new file mode 100644
index 00000000..a0e49a3b
--- /dev/null
+++ b/src/test/test.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file