From eb7c113aaf48409c603ab4834a1d37bcc15e2535 Mon Sep 17 00:00:00 2001 From: mrotteveel Date: Sun, 6 May 2012 15:53:55 +0000 Subject: [PATCH] JDBC-226 / JDBC-252 : Workaround for read only tables in OpenOffice / LibreOffice Base when using roles to connect --- .../jdbc/AbstractDatabaseMetaData.java | 86 +++++++------- .../jdbc/oo/OODatabaseMetaData.java | 107 ++++++++++++------ 2 files changed, 120 insertions(+), 73 deletions(-) diff --git a/src/main/org/firebirdsql/jdbc/AbstractDatabaseMetaData.java b/src/main/org/firebirdsql/jdbc/AbstractDatabaseMetaData.java index 25742f4252..76d481c907 100644 --- a/src/main/org/firebirdsql/jdbc/AbstractDatabaseMetaData.java +++ b/src/main/org/firebirdsql/jdbc/AbstractDatabaseMetaData.java @@ -3261,8 +3261,6 @@ else if (privilege.equals("M")) return new FBResultSet(xsqlvars, rows); } - - private static final String GET_TABLE_PRIVILEGES_START = "select" + " null as TABLE_CAT, " + " null as TABLE_SCHEM," @@ -3316,6 +3314,40 @@ public ResultSet getTablePrivileges(String catalog, String schemaPattern, checkCatalogAndSchema(catalog, schemaPattern); tableNamePattern = stripQuotes(stripEscape(tableNamePattern), true); + XSQLVAR[] xsqlvars = buildTablePrivilegeRSMetaData(); + + Clause tableClause = new Clause("RDB$RELATION_NAME", tableNamePattern); + + String sql = GET_TABLE_PRIVILEGES_START; + sql += tableClause.getCondition(); + sql += GET_TABLE_PRIVILEGES_END; + + // check the original case identifiers first + ArrayList params = new ArrayList(); + if (!tableClause.getCondition().equals("")) { + params.add(tableClause.getOriginalCaseValue()); + } + + ResultSet rs = doQuery(sql, params); + + // if nothing found, check the uppercased identifiers + if (!rs.next()) { + params.clear(); + if (!tableClause.getCondition().equals("")) { + params.add(tableClause.getValue()); + } + + rs = doQuery(sql, params); + + // if nothing found, return an empty result set + if (!rs.next()) + return new FBResultSet(xsqlvars, new ArrayList()); + } + + return processTablePrivileges(xsqlvars, rs); + } + + protected final XSQLVAR[] buildTablePrivilegeRSMetaData() { XSQLVAR[] xsqlvars = new XSQLVAR[7]; xsqlvars[0] = new XSQLVAR(); @@ -3359,45 +3391,21 @@ public ResultSet getTablePrivileges(String catalog, String schemaPattern, xsqlvars[6].sqllen = 31; xsqlvars[6].sqlname = "IS_GRANTABLE"; xsqlvars[6].relname = "TABLEPRIV"; - - Clause tableClause = new Clause("RDB$RELATION_NAME", tableNamePattern); - - String sql = GET_TABLE_PRIVILEGES_START; - sql += tableClause.getCondition(); - sql += GET_TABLE_PRIVILEGES_END; - // check the original case identifiers first - ArrayList params = new ArrayList(); - if (!tableClause.getCondition().equals("")) { - params.add(tableClause.getOriginalCaseValue()); - } - + return xsqlvars; + } + + protected final FBResultSet processTablePrivileges(XSQLVAR[] xsqlvars, ResultSet fbTablePrivileges) throws SQLException { ArrayList rows = new ArrayList(); - ResultSet rs = doQuery(sql, params); - - // if nothing found, check the uppercased identifiers - if (!rs.next()) { - params.clear(); - if (!tableClause.getCondition().equals("")) { - params.add(tableClause.getValue()); - } - - rs = doQuery(sql, params); - - // if nothing found, return an empty result set - if (!rs.next()) - return new FBResultSet(xsqlvars, rows); - - } do { byte[][] row = new byte[7][]; row[0] = null; row[1] = null; - row[2] = getBytes(rs.getString("TABLE_NAME")); - row[3] = getBytes(rs.getString("GRANTOR")); - row[4] = getBytes(rs.getString("GRANTEE")); - String privilege = rs.getString("PRIVILEGE"); + row[2] = getBytes(fbTablePrivileges.getString("TABLE_NAME")); + row[3] = getBytes(fbTablePrivileges.getString("GRANTOR")); + row[4] = getBytes(fbTablePrivileges.getString("GRANTEE")); + String privilege = fbTablePrivileges.getString("PRIVILEGE"); if (privilege.equals("A")) row[5] = getBytes("ALL"); else if (privilege.equals("S")) @@ -3409,17 +3417,17 @@ else if (privilege.equals("I")) else if (privilege.equals("U")) row[5] = getBytes("UPDATE"); else if (privilege.equals("R")) - row[5] = getBytes("REFERENCE"); + row[5] = getBytes("REFERENCE"); // TODO: JDBC spec specifies REFRENCES (yes: typo and + S) else if (privilege.equals("M")) row[5] = getBytes("MEMBEROF"); - int isGrantable = rs.getShort("IS_GRANTABLE"); + int isGrantable = fbTablePrivileges.getShort("IS_GRANTABLE"); if (isGrantable==0) row[6] = getBytes("NO"); else row[6] = getBytes("YES"); rows.add(row); - } while (rs.next()); + } while (fbTablePrivileges.next()); return new FBResultSet(xsqlvars, rows); } @@ -6154,14 +6162,14 @@ public String getViewSourceCode(String viewName) throws SQLException { } - private void checkCatalogAndSchema(String catalog, String schema) throws SQLException { + protected void checkCatalogAndSchema(String catalog, String schema) throws SQLException { /* * we ignore incorrect catalog and schema specification as * suggested by Thomas Kellerer in JDBC Forum */ } - private class Clause { + protected class Clause { private String condition = ""; private String value; private String originalCaseValue; diff --git a/src/openoffice/org/firebirdsql/jdbc/oo/OODatabaseMetaData.java b/src/openoffice/org/firebirdsql/jdbc/oo/OODatabaseMetaData.java index 639a2443d8..6e21717b24 100644 --- a/src/openoffice/org/firebirdsql/jdbc/oo/OODatabaseMetaData.java +++ b/src/openoffice/org/firebirdsql/jdbc/oo/OODatabaseMetaData.java @@ -185,13 +185,84 @@ public ResultSet getSuperTypes(String catalog, String schemaPattern, return super.getSuperTypes(catalog, schemaPattern, tableNamePattern); } + + private static final String GET_TABLE_PRIVILEGES_START_1 = + "SELECT " + + "null as TABLE_CAT, " + + "null as TABLE_SCHEM, " + + "RDB$RELATION_NAME as TABLE_NAME, " + + "RDB$GRANTOR as GRANTOR, " + + "RDB$USER as GRANTEE, " + + "RDB$PRIVILEGE as PRIVILEGE, " + + "RDB$GRANT_OPTION as IS_GRANTABLE " + + "FROM RDB$USER_PRIVILEGES " + + "WHERE "; + private static final String GET_TABLE_PRIVILEGES_END_1 = + " CURRENT_USER IN (RDB$USER, RDB$GRANTOR) AND RDB$FIELD_NAME IS NULL AND RDB$OBJECT_TYPE = 0"; + private static final String GET_TABLE_PRIVILEGES_START_2 = + "UNION " + + "SELECT " + + "null as TABLE_CAT, " + + "null as TABLE_SCHEM, " + + "RDB$RELATION_NAME as TABLE_NAME, " + + "RDB$GRANTOR as GRANTOR, " + + "CURRENT_USER as GRANTEE, " + + "RDB$PRIVILEGE as PRIVILEGE, " + + "RDB$GRANT_OPTION as IS_GRANTABLE " + + "FROM RDB$USER_PRIVILEGES " + + "WHERE "; + private static final String GET_TABLE_PRIVILEGES_END_2 = + " RDB$USER = CURRENT_ROLE AND RDB$FIELD_NAME IS NULL AND RDB$OBJECT_TYPE = 0 " + + "ORDER BY 3, 6"; public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { if (DEFAULT_SCHEMA.equals(schemaPattern)) schemaPattern = null; - return super.getTablePrivileges(catalog, schemaPattern, - tableNamePattern); + checkCatalogAndSchema(catalog, schemaPattern); + tableNamePattern = stripQuotes(stripEscape(tableNamePattern), true); + + XSQLVAR[] xsqlvars = buildTablePrivilegeRSMetaData(); + + Clause tableClause1 = new Clause("RDB$RELATION_NAME", tableNamePattern); + Clause tableClause2 = new Clause("RDB$RELATION_NAME", tableNamePattern); + + String sql = GET_TABLE_PRIVILEGES_START_1; + sql += tableClause1.getCondition(); + sql += GET_TABLE_PRIVILEGES_END_1; + sql += GET_TABLE_PRIVILEGES_START_2; + sql += tableClause2.getCondition(); + sql += GET_TABLE_PRIVILEGES_END_2; + + // check the original case identifiers first + ArrayList params = new ArrayList(); + if (!tableClause1.getCondition().equals("")) { + params.add(tableClause1.getOriginalCaseValue()); + } + if (!tableClause2.getCondition().equals("")) { + params.add(tableClause2.getOriginalCaseValue()); + } + + ResultSet rs = doQuery(sql, params); + + // if nothing found, check the uppercased identifiers + if (!rs.next()) { + params.clear(); + if (!tableClause1.getCondition().equals("")) { + params.add(tableClause1.getValue()); + } + if (!tableClause2.getCondition().equals("")) { + params.add(tableClause2.getValue()); + } + + rs = doQuery(sql, params); + + // if nothing found, return an empty result set + if (!rs.next()) + return new FBResultSet(xsqlvars, new ArrayList()); + } + + return processTablePrivileges(xsqlvars, rs); } public String stripEscape(String pattern) { @@ -206,36 +277,4 @@ public String stripQuotes(String pattern) { return pattern; } } - - private class Clause { - - private String condition = ""; - - private String value; - - public Clause(String columnName, String pattern) { - if (pattern == null) { - return; - } else if (isAllCondition(pattern)) { - // do nothing to tableCondition - return; - } else if (hasNoWildcards(pattern)) { - value = stripQuotes(stripEscape(pattern)); - condition = columnName + " = ? and "; - } else { - value = stripQuotes(pattern) + SPACES + "%"; - condition = columnName + " || '" + SPACES - + "' like ? escape '\\' and "; - } - } - - public String getCondition() { - return condition; - } - - public String getValue() { - return value; - } - } - }