[Schmitzm-commits] r1819 - in trunk/schmitzm-db: . .settings src/main/java src/main/java/de src/main/java/de/schmitzm src/main/java/de/schmitzm/postgres src/main/java/de/schmitzm/sql src/main/java/postgres src/main/java/sql
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Sat Jan 14 21:45:17 CET 2012
Author: alfonx
Date: 2012-01-14 21:45:15 +0100 (Sat, 14 Jan 2012)
New Revision: 1819
Added:
trunk/schmitzm-db/src/main/java/de/
trunk/schmitzm-db/src/main/java/de/schmitzm/
trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/
trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/PGUtil.java
trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/SqlQueryStat.java
trunk/schmitzm-db/src/main/java/de/schmitzm/sql/
trunk/schmitzm-db/src/main/java/de/schmitzm/sql/SqlUtil.java
Removed:
trunk/schmitzm-db/src/main/java/postgres/PGUtil.java
trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java
trunk/schmitzm-db/src/main/java/sql/SqlUtil.java
Modified:
trunk/schmitzm-db/.classpath
trunk/schmitzm-db/.settings/org.eclipse.core.resources.prefs
Log:
neues modul schmitzm-db
Modified: trunk/schmitzm-db/.classpath
===================================================================
--- trunk/schmitzm-db/.classpath 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/.classpath 2012-01-14 20:45:15 UTC (rev 1819)
@@ -1,14 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry excluding="**/.svn" kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
- <classpathentry kind="lib" path="/home/stefan/.m2/repository/postgresql/postgresql/9.1-901.jdbc4/postgresql-9.1-901.jdbc4.jar">
- <attributes>
- <attribute name="maven.groupId" value="postgresql"/>
- <attribute name="maven.artifactId" value="postgresql"/>
- <attribute name="maven.version" value="9.1-901.jdbc4"/>
- <attribute name="maven.scope" value="compile"/>
- </attributes>
- </classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
Modified: trunk/schmitzm-db/.settings/org.eclipse.core.resources.prefs
===================================================================
--- trunk/schmitzm-db/.settings/org.eclipse.core.resources.prefs 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/.settings/org.eclipse.core.resources.prefs 2012-01-14 20:45:15 UTC (rev 1819)
@@ -1,3 +1,4 @@
-#Sat Jan 14 21:27:48 CET 2012
+#Sat Jan 14 21:39:26 CET 2012
eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
encoding/<project>=UTF-8
Copied: trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/PGUtil.java (from rev 1818, trunk/schmitzm-db/src/main/java/postgres/PGUtil.java)
===================================================================
--- trunk/schmitzm-db/src/main/java/postgres/PGUtil.java 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/PGUtil.java 2012-01-14 20:45:15 UTC (rev 1819)
@@ -0,0 +1,971 @@
+package de.schmitzm.postgres;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.postgresql.util.PGInterval;
+
+import de.schmitzm.lang.LangUtil;
+
+/**
+ * Hilfsmethoden für PostgreSQL. Die Dependency soll nur {@link Connection} sein. In Hibernate kann über #doWork eine
+ * {@link Connection} erhalten werden.
+ */
+public class PGUtil {
+ static final Logger log = Logger.getLogger(PGUtil.class);
+
+ /**
+ * PostgreSQL Privilegien die per Grant einer Tabelle zugeordnet werden können.<br/>
+ *
+ * @see http://www.postgresql.org/docs/9.1/static/sql-grant.html
+ */
+ public enum Privileges {
+ SELECT, INSERT, UPDATE, DELETE, REFERENCES, TEMPORARY, ALL_PRIVILEGES("ALL PRIVILEGES");
+
+ String sql;
+
+ Privileges() {
+ this.sql = super.toString();
+ }
+
+ Privileges(String sql) {
+ this.sql = sql;
+ }
+
+ @Override
+ public String toString() {
+ return this.sql;
+ }
+ }
+
+ /**
+ * Fügt Privilegien für eine Rolle einer Tabelle hinzu.
+ *
+ * @param tablename
+ * Tabellennamen, optional mit "schema.tablename"
+ * @param targetRole
+ * Darf PUBLIC sein, oder Name einer ROLLE.
+ * @param privileges
+ * List der zuzuordnenden Privilegien
+ * @throws SQLException
+ */
+ public static void grantPrivilegesOnTable(Connection c, String targetRole, String tablename,
+ Privileges... privileges) throws SQLException {
+ // GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
+ String sql = "GRANT " + LangUtil.stringConcatWithSep(",", (Object[]) privileges) + " ON " + tablename + " TO "
+ + targetRole;
+ c.createStatement().executeUpdate(sql);
+ }
+
+ /**
+ * Entfernt Privilegien für eine Rolle von einre Tabelle.
+ *
+ * @param tablename
+ * Tabellennamen, optional mit "schema.tablename"
+ * @param privileges
+ * List der zuzuordnenden Privilegien
+ * @throws SQLException
+ */
+ public static void revokePrivilegesOnTable(Connection c, String tablename, String targetRole,
+ Privileges... privileges) throws SQLException {
+ // GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
+ String sql = "REVOKE " + LangUtil.stringConcatWithSep(",", (Object[]) privileges) + " ON " + tablename
+ + " FROM " + targetRole;
+ c.createStatement().executeUpdate(sql);
+ }
+
+ /**
+ * Erstellt eine neue Rolle
+ *
+ * @param rolename
+ * Name der neuen Rolle
+ * @param inhRoles
+ * Rollen in denen die neue Rolle Mitglied ist
+ */
+ public static void createRole(Connection c, String rolename, String... inhRoles) throws SQLException {
+ String sql = "CREATE ROLE " + rolename;
+ c.createStatement().executeUpdate(sql);
+ for (String inhRole : inhRoles)
+ c.createStatement().executeUpdate("GRANT " + inhRole + " TO " + rolename);
+ }
+
+ /**
+ * Erstellt eine neue Rolle, wenn diese noch nicht existiert.
+ *
+ * @param rolename
+ * Name der neuen Rolle
+ * @param inhRoles
+ * Rollen in denen die neue Rolle Mitglied ist
+ */
+ public static void createRoleIfNotExists(Connection c, String rolename, String... inhRoles) throws SQLException {
+ if (existsRole(c, rolename))
+ return;
+ createRole(c, rolename, inhRoles);
+ }
+
+ /**
+ * Querys the <code>geometry_columns</code> table is part of every POSTGIS installation and must/should describe the
+ * geometry columns and tables.
+ */
+ static public String[] getColumnsDescribedInGeometryColumnsTable(Statement s) {
+ String[] columns = new String[0];
+ try {
+ ResultSet rs = s.executeQuery("SELECT f_table_name FROM geometry_columns;");
+ try {
+
+ while (rs.next()) {
+ columns = LangUtil.extendArray(columns, rs.getString(1));
+ }
+ } finally {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ log.error(e, e);
+ }
+
+ return columns;
+
+ }
+
+ /**
+ * Creates or Updates
+ *
+ * @param tableName
+ * @param geoColumnName
+ * @param srid
+ */
+ @Deprecated
+ // tut noch nicht
+ public static void createOrUpdateGeometrysColumnsEntry(String tableName, String geoColumnName, int srid) {
+
+ String createGeometryEntrySQL = "INSERT INTO geometry_columns (f_table_catalog, f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, \"type\") VALUES ( '', 'public', '"
+ + tableName + "', '" + geoColumnName + "', 2, " + srid + ",'MULTIPOLYGON' ) LIMIT 1;";
+ }
+
+ // TODO isGeoColumn();
+
+ /**
+ * @param binding
+ * Eine "einfache" Javaklasse, die in PG abgebildet werden soll.
+ * @return einen PG-spezifischen Datentypenamen für einen Javatyp zurück, z.b. "double precision" für
+ * <code>Double.class</code>
+ */
+ public static String getColTypeName(Class<?> binding) {
+
+ if (binding.isAssignableFrom(Double.class)) {
+ return "double precision"; // eg 'number' at oracle
+ } else if (binding.isAssignableFrom(String.class)) {
+ return "text";
+ } else if (binding.isAssignableFrom(Integer.class)) {
+ return "integer";
+ } else if (binding.isAssignableFrom(Long.class)) {
+ return "bigint";
+ }
+
+ throw new RuntimeException("DB Type mapping for " + binding + " not yet implemented.");
+ }
+
+ /**
+ * Legt ein Schema an, wenn es vorher nicht existierte.
+ *
+ * @return <code>true</code> wenn das Schema neu angelegt wurde.
+ */
+ public static boolean createSchemaIfNotExists(Connection c, String schemaname) throws SQLException {
+ if (!existsSchema(c, schemaname)) {
+ c.createStatement().execute("create schema " + schemaname.toLowerCase());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Liefert <code>true</code> wenn ein Schema mit dem Namen in der PG Datenbank existiert.
+ */
+ public static boolean existsSchema(Connection c, String schemaname) throws SQLException {
+ String sql = "select 1 from pg_catalog.pg_namespace where nspname = '" + schemaname.toLowerCase() + "'";
+ ResultSet rs = c.createStatement().executeQuery(sql);
+ try {
+ return rs.next();
+ } finally {
+ rs.close();
+ }
+
+ }
+
+ /**
+ * Liefert eine Liste der Rollen in denen der Übergebenen USER (Login role) ist. <br/>
+ * Tested with PG 8.4
+ */
+ public static List<String> listRolesForUser(Connection c, String username) throws SQLException {
+ List<String> roles = new ArrayList<String>();
+ String sql = "select rolname from pg_user join pg_auth_members on (pg_user.usesysid=pg_auth_members.member) join pg_roles on (pg_roles.oid=pg_auth_members.roleid) where pg_user.usename='"
+ + username.toLowerCase() + "'";
+ ResultSet rs = c.createStatement().executeQuery(sql);
+ try {
+ while (rs.next()) {
+ roles.add(rs.getString(1));
+ }
+ } finally {
+ rs.close();
+ }
+ return roles;
+ }
+
+ /**
+ * Liefert alle Benutzer der DB zurück.
+ *
+ * @throws SQLException
+ */
+ public static List<String> listUsers(Connection c) throws SQLException {
+ List<String> roles = new ArrayList<String>();
+ ResultSet rs = c.createStatement().executeQuery("select * from pg_user");
+ try {
+ while (rs.next()) {
+ roles.add(rs.getString(1));
+ }
+ } finally {
+ rs.close();
+ }
+ return roles;
+ }
+
+ /**
+ * Liste aller Tabellennamen in diesem Schema, ohne die Schemaangabe im Namen. (Also 'anreden' und nicht
+ * 'public.anreden') <br/>
+ * Tested with PG 8.4
+ *
+ * @param schemaname
+ * if <code>null</code>, <code>public</code> is used.
+ */
+ public static List<String> listTablesInSchema(Connection c, String schemaname) throws SQLException {
+ List<String> tables = new ArrayList<String>();
+
+ String sql = "select tablename from pg_tables where schemaname = '" + schemaname.toLowerCase() + "'";
+ ResultSet rs = c.createStatement().executeQuery(sql);
+ try {
+ while (rs.next()) {
+ tables.add(rs.getString(1));
+ }
+ } finally {
+ rs.close();
+ }
+ return tables;
+ }
+
+ /**
+ * Liefert <code>true</code> wenn der Benutzername im DBMS Superuser ist.
+ */
+ public static boolean isSuperuser(Connection c, String username) throws SQLException {
+ ResultSet rs = c.createStatement().executeQuery(
+ "select usesuper from pg_user where usename = '" + username + "' and usesuper = true");
+ try {
+ if (rs.next()) {
+ return true;
+ }
+ } finally {
+ rs.close();
+ }
+ return false;
+ }
+
+ public static boolean existsRole(Connection c, String rolename) throws SQLException {
+ String sql = "select count(1) from pg_roles where rolname = '" + rolename.toLowerCase() + "'";
+ ResultSet rs = c.createStatement().executeQuery(sql);
+ try {
+ if (rs.next())
+ return rs.getInt(1) > 0;
+ } finally {
+ rs.close();
+ }
+ return false;
+ }
+
+ public static void removeAllPrivilegesFrom(Connection c, String rolename, String tablename) throws SQLException {
+ c.createStatement().executeUpdate(
+ "revoke all on TABLE " + tablename.toLowerCase() + " from " + rolename.toLowerCase() + " cascade");
+ }
+
+ /**
+ * Löscht eine Rolle wenn sie vorher existiert
+ */
+ public static void dropRoleIfExists(Connection c, String rolename) throws SQLException {
+ c.createStatement().executeUpdate("drop role if exists " + rolename.toLowerCase());
+ }
+
+ /**
+ * Löscht einen Trigger wenn er vorher existierte.
+ *
+ * @param c
+ * @param triggerName
+ * @param tableName
+ */
+ public static void dropTriggerIfExists(Connection c, String triggerName, String tableName) throws SQLException {
+ c.createStatement().executeUpdate("drop TRIGGER if exists " + triggerName.toLowerCase() + " ON " + tableName);
+ }
+
+ /**
+ *
+ * @param c
+ * @param name
+ * z.B.: keckformel wird dann zu keckformel()
+ * @param plCommands
+ * z.B.
+ * <code>NEW.kpk_kreis = NEW.risiko_soz+NEW.risiko_emo+NEW.risiko_moti +NEW.risiko_spr+NEW.risiko_wohl;</code>
+ * OHNE <code>RETURN NEW</code>, das wird automatisch angehangen.
+ * @throws SQLException
+ */
+ public static void createOrReplaceTriggerFunction(Connection c, String name, String plCommands) throws SQLException {
+ // System.err.println(plCommands);
+
+ // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name
+ // + "$\nBEGIN\n?\nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
+ // PreparedStatement ps = c.prepareStatement(sql);
+ // ps.setString(0, plCommands);
+ // ps.executeUpdate();
+
+ // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name + "$\nBEGIN\n "
+ // + plCommands + " \nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
+ // c.createStatement().executeUpdate(sql);
+
+ createOrReplaceFunction(c, name, null, "TRIGGER", null, plCommands + "\nRETURN NEW");
+ }
+
+ /**
+ *
+ * @param c
+ * @param name
+ * z.B.: keckformel wird dann zu keckformel()
+ * @param parameters
+ * Parameter der Funcktion, kann <code>null</code> sein.
+ * @param returns
+ * z.B. <code>TRIGGER</code> oder <code>SETOF bigint</code> oder "void"
+ * @param declare
+ * Declare block oder <code>null</code>
+ * @param plCommands
+ * z.B. NEW.kpk_kreis = NEW.risiko_soz+NEW.risiko_emo+NEW.risiko_moti +NEW.risiko_spr+NEW.risiko_wohl;
+ */
+ public static void createOrReplaceFunction(Connection c, String name, String parameters, String returns,
+ String declare, String plCommands) throws SQLException {
+ // System.err.println(plCommands);
+
+ // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name
+ // + "$\nBEGIN\n?\nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
+ // PreparedStatement ps = c.prepareStatement(sql);
+ // ps.setString(0, plCommands);
+ // ps.executeUpdate();
+
+ parameters = LangUtil.removeWhitespacesToEmpty(parameters);
+ declare = LangUtil.removeWhitespacesToEmpty(declare);
+
+ String sql = "CREATE OR REPLACE FUNCTION " + name + "(" + parameters + ")" + " RETURNS " + returns + " AS $$\n"
+ + "DECLARE\n" + declare + "\n" + "BEGIN\n " + plCommands + ";" + "\nEND;\n$$ LANGUAGE 'plpgsql'";
+ c.createStatement().executeUpdate(sql);
+ }
+
+ /**
+ * Erstellt einen <code>FOR EACH ROW EXECUTE PROCEDURE</code> trigger für eine Tabelle
+ *
+ * @param c
+ * @param triggerName
+ * @param type
+ * z.B. "BEFORE INSERT OR UPDATE"
+ * @param tableName
+ * @param plCommands
+ * PSQL commands, e.g.<br/>
+ * <code>
+ IF ((TG_OP = 'UPDATE') or (TG_OP = 'INSERT') ) THEN
+ INSERT INTO workqueue values (NEW.id);
+ RETURN NEW;
+ END IF;
+ </code>
+ */
+ public static void createOrRecreateTrigger(Connection c, String triggerName, String type, String tableName,
+ String plCommands) throws SQLException {
+ dropTriggerIfExists(c, triggerName, tableName);
+ createOrReplaceTriggerFunction(c, triggerName + "_fn", plCommands);
+ c.createStatement().executeUpdate(
+ "CREATE TRIGGER " + triggerName + " " + type + " ON " + tableName + " FOR EACH ROW EXECUTE PROCEDURE "
+ + triggerName + "_fn" + "()");
+ }
+
+ /**
+ * @param tableName
+ * e.g. 'inseratabfragen_kvps'
+ * @param columns
+ * e.g. 'inseratabfrage_id'
+ * @param idxNamePostfix
+ * e.g. 'idx1'
+ * @param unique
+ * <code>true</code> if the columns are unique. A UNIQUE INDEX will be created.
+ */
+ public static void addIndex(Connection c, final String tableName, final String columns, String idxPostfix,
+ final boolean unique) throws SQLException {
+ addIndex(c, tableName, columns, idxPostfix, unique, null, null, false, null);
+ }
+
+ /**
+ * Liefert eine Liste aller Indexnamen die für eine Tabelle existieren. Der Tabellenname wird mit <code>like</code>
+ * verglichen, darf also <code>%</code> enthalten.<br/>
+ * Achtung: Diese abfrage ist nicht Schema-Spezifisch. Eine schema. Angabe vor dem tabellennamen wird automatisch
+ * entfernt.
+ */
+ public static List<String> listIndexesForTable(Connection c, String tableName) throws SQLException {
+ Statement s = c.createStatement();
+
+ if (tableName.contains("."))
+ tableName = tableName.substring(tableName.indexOf(".") + 1, tableName.length());
+
+ List<String> idxes = new ArrayList<String>();
+
+ // , array_to_string(array_agg(a.attname), ', ') as column_names
+ String sql = "select t.relname as table_name, i.relname as index_name from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = 'r' and t.relname like '"
+ + tableName + "' group by t.relname, i.relname order by t.relname, i.relname";
+
+ ResultSet rs = s.executeQuery(sql);
+ try {
+ while (rs.next()) {
+ idxes.add(rs.getString(2));
+ }
+ } finally {
+ rs.close();
+ }
+
+ return idxes;
+
+ }
+
+ /**
+ * @param tableName
+ * e.g. 'inseratabfragen_kvps'
+ * @param columns
+ * e.g. 'inseratabfrage_id'
+ * @param idxNamePostfix
+ * e.g. 'idx1'
+ * @param unique
+ * <code>true</code> if the columns are unique. A UNIQUE INDEX will be created.
+ * @param tablespace
+ * <code>null</code> oder der name des tablespace in dem der Index liegen soll.
+ * @param type
+ * <code>null</code> für DB default oder "hash" oder "btree" oder "gin" etc...
+ * @param forceRecreationIfExistsAlready
+ * wenn <code>true</code> dann werden der Index vorher gedroppt falls er exisitert.
+ * @param fillFactor
+ * Wert von >0. -> 1. Bei .5 wird für den Index doppelt so viel Platz reserviert wie aktuell benötig, um
+ * auf weiteres Wachstum der Tabelle ohne Indexfragmentierung reagieren zu können.
+ */
+ public static void addIndex(Connection c, final String tableName, final String columns, String idxPostfix,
+ final boolean unique, String tablespace, String type, boolean forceRecreationIfExistsAlready,
+ Double fillFactor) throws SQLException {
+ String idxNameWithDot = tableName + "_" + idxPostfix;
+ final String idxName = idxNameWithDot.replace(".", "_");
+
+ // Wenn der Tablename ein Schema mit "schema.name" enthält, dann liefert
+ // listIndexesForTable hier ein schema_table im Index-Namen zurück. Der
+ // "." wird also zu einem "_"
+ for (String existIdxName : listIndexesForTable(c, tableName)) {
+ if (existIdxName.equalsIgnoreCase(idxName.replaceFirst("\\.", "_"))) {
+ // Existiert bereits.
+
+ if (!forceRecreationIfExistsAlready)
+ return;
+
+ log.info("Aufgrund von forceRecreationIfExistsAlready=true wird der Index " + idxNameWithDot
+ + " jetzt gedroppt.");
+
+ Statement s = c.createStatement();
+
+ // Hier die Schreibweise mit . für schematrennung verwenden
+ final String queryString = "DROP INDEX " + idxNameWithDot;
+ try {
+ s.execute(queryString);
+ c.commit();
+ log.debug("Index dropped: " + queryString);
+ } catch (SQLException e) {
+ c.rollback();
+ Throwable cause = e;
+ if (e.getCause() != null)
+ cause = e.getCause();
+
+ // keine Ausgabe bei: already EXISTs, EXISTiert
+ // bereits,
+ // ...
+ // Ex abfangen, wenn IDX schon existiert
+
+ String msg = cause.getMessage();
+ log.error(e.getLocalizedMessage(), e);
+ return;
+ }
+
+ break;
+
+ }
+ }
+
+ Statement s = c.createStatement();
+
+ if (fillFactor != null && (fillFactor <= 0. || fillFactor > 1.))
+ throw new IllegalArgumentException("fillFactor muss großer 0 und kleinergleich 1 sein.");
+
+ String sqlFillFactor = "";
+ if (fillFactor != null)
+ sqlFillFactor = " WITH (FILLFACTOR=" + (int) (fillFactor * 100) + ") ";
+
+ String sqlTableSpace = (tablespace == null || tablespace.equalsIgnoreCase("null") || !existsTablespace(c,
+ tableName)) ? "" : " TABLESPACE " + tablespace;
+
+ String sqlUsing = type == null ? "" : " USING " + type;
+
+ final String queryString = "CREATE " + (unique ? "UNIQUE " : "") + "INDEX " + idxName + " ON " + tableName
+ + sqlUsing + " (" + columns + ") " + sqlFillFactor + sqlTableSpace;
+ try {
+ s.execute(queryString);
+ c.commit();
+ log.info("Neuen Index erstellt: " + queryString);
+ } catch (SQLException e) {
+ c.rollback();
+ Throwable cause = e;
+ if (e.getCause() != null)
+ cause = e.getCause();
+
+ // keine Ausgabe bei: already EXISTs, EXISTiert
+ // bereits,
+ // ...
+ // Ex abfangen, wenn IDX schon existiert
+
+ String msg = cause.getMessage();
+ if (msg.endsWith("already exists") || msg.endsWith("existiert bereits")) {
+ // TO NOTHING, IDX already exists
+ log.info("Index existierte bereits, nicht neuerstellt: " + queryString);
+ } else
+ log.error(e.getLocalizedMessage(), e);
+
+ }
+
+ }
+
+ /**
+ * Liefert <code>true</code> wenn ein tablespace mit dem Namen existiert.
+ *
+ * @throws SQLException
+ */
+ private static boolean existsTablespace(Connection c, String spaceName) throws SQLException {
+
+ // SELECT count(1) FROM pg_tablespace where spcname = 'spcname';
+ String stmtSql = "SELECT COUNT(*) FROM pg_tablespace where spcname = '" + spaceName + "'";
+
+ PreparedStatement stmt = c.prepareStatement(stmtSql);
+ stmt.execute();
+
+ ResultSet result = stmt.getResultSet();
+ try {
+ int count = 0;
+ if (result.next())
+ count = result.getInt(1);
+
+ return count > 0;
+ } finally {
+ result.close();
+ stmt.close();
+ }
+
+ }
+
+ /**
+ * Fügt einen Benutzer zu einer Rolle hinzu. Wenn der benutzer bereits in der Rolle enthalten ist, wird keine
+ * Exception geschmisssen.
+ *
+ * @throws SQLException
+ */
+ public static void grantRoleToUser(Connection c, String rolename, String username) throws SQLException {
+ c.createStatement().executeUpdate("GRANT " + rolename + " TO " + username);
+ }
+
+ /**
+ * Der : (Doppelpunkt) hat in PSQL eine besondere Bedeutung. Er wind mit dieser methode escaped. Diese Methode
+ * sollte mit <code>like E'"+PGUtil.escape(...)+"'</code> verwendet werden.
+ */
+ public static String escape(String key) {
+ key = key.replaceAll(":", "\\:");
+ return key;
+ }
+
+ /**
+ * Liefert die Anzahl der offenen Sessions zur Datenbank.
+ *
+ * @param c
+ * DB-Verbindung
+ * @param dbName
+ * Name der Datenbank fuer die die Sessions gezaehlt werden (kann {@code null} sein)
+ * @param userName
+ * Name des Users fuer den die Sessions gezaehlt werden (kann {@code null} sein)
+ */
+ public static int getOpenSessionCount(Connection c, String dbName, String userName) throws SQLException {
+ return getOpenSessionCount(c, dbName, userName, null);
+ }
+
+ /**
+ * Liefert die Anzahl der offenen Sessions zur Datenbank.
+ *
+ * @param c
+ * DB-Verbindung
+ * @param dbName
+ * Name der Datenbank fuer die die Sessions gezaehlt werden (kann {@code null} sein)
+ * @param userName
+ * Name des Users fuer den die Sessions gezaehlt werden (kann {@code null} sein)
+ * @param queryLike
+ * like-Beindung auf die Query die in der Session ausgeführt wird, oder <code>null</code>
+ */
+ public static int getOpenSessionCount(Connection c, String dbName, String userName, String queryLike)
+ throws SQLException {
+ String stmtSql = "SELECT COUNT(*) FROM pg_stat_activity WHERE TRUE";
+
+ if (dbName != null)
+ stmtSql += " AND datname = ?";
+ if (userName != null)
+ stmtSql += " AND usename = ?";
+ if (queryLike != null) {
+ stmtSql += " AND current_query like '" + queryLike + "'";
+ }
+
+ PreparedStatement stmt = c.prepareStatement(stmtSql);
+ if (dbName != null)
+ stmt.setString(1, dbName);
+ if (userName != null)
+ stmt.setString(2, userName);
+ stmt.execute();
+
+ ResultSet result = stmt.getResultSet();
+ try {
+ int count = 0;
+ if (result.next())
+ count = result.getInt(1);
+
+ return count;
+ } finally {
+ result.close();
+ stmt.close();
+ }
+ }
+
+ /**
+ * Liefert <code>true</code> wenn eine Spalte mit dem Namen in der angegebenen Tabelle existiert. Die Tablle darf
+ * optional mit "schema." prefixiert werden.
+ */
+ public static boolean existsColumn(Connection c, String tableName, String columnName) throws SQLException {
+
+ String schema = "public";
+
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ ResultSet nativeCheckExistsColumnQuery = c.createStatement().executeQuery(
+ "SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME = '" + columnName.toLowerCase()
+ + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
+ return nativeCheckExistsColumnQuery.next();
+ }
+
+ /**
+ * Existiert ein relationsname als View?
+ *
+ * @param viewName
+ * Darf eine Schemaangabe mit . Trenner enthalten.
+ * @throws SQLException
+ */
+ public static boolean existsView(Connection c, String viewName) throws SQLException {
+
+ String schema = "public";
+
+ if (viewName.contains(".")) {
+ final String[] split = viewName.split("\\.");
+ schema = split[0];
+ viewName = split[1];
+ }
+
+ final String checkView = "SELECT * FROM information_schema.VIEWS where table_schema = '" + schema
+ + "' and table_name = '" + viewName + "' LIMIT 1";
+ ResultSet rs = c.createStatement().executeQuery(checkView);
+
+ try {
+ return rs.next();
+ } finally {
+ rs.close();
+ }
+ }
+
+ public static void dropViewIfExists(Connection c, String viewName) throws SQLException {
+ final String dropView = "DROP VIEW IF EXISTS " + viewName;
+ c.createStatement().executeUpdate(dropView);
+ }
+
+ /**
+ * Liefert eine Liste der aktuell laufenden Queries und ihrere Laufzeiten zurück. Der 2. Teil der Rückgabepaare ist
+ * ein String der einem PG Interval entspricht. Dieses kann mit der Klasse PGInterval geparst werden.<br/>
+ *
+ * @param datName
+ * <code>null</code> oder der Datenbankname, auf den die Abfrage gefiltert werden soll.
+ *
+ * @param minSecondsRunning
+ * <code>null</code> oder die zurückgegebenen Anfragen müssen mindestens soviele Sekunden schon laufen.
+ */
+ static public List<SqlQueryStat> listQueries(Connection c, String datName, Integer minSecondsRunning)
+ throws SQLException {
+ ArrayList<SqlQueryStat> result = new ArrayList<SqlQueryStat>();
+
+ String where = "where current_query not like '%IDLE%' ";
+
+ if (datName != null)
+ where += " and datname like '" + datName + "'";
+
+ if (minSecondsRunning != null) {
+ if (minSecondsRunning < 0)
+ throw new IllegalStateException();
+
+ where += " and age (now(),query_start) >= interval '" + minSecondsRunning + " second' ";
+ }
+
+ final String sql = "select current_query, age (now(),query_start) as qage, waiting, procpid from pg_stat_activity "
+ + where + " order by qage desc";
+ ResultSet rs = c.createStatement().executeQuery(sql);
+
+ try {
+ while (rs.next()) {
+ String q = rs.getString(1);
+ String age = rs.getString(2);
+ boolean waiting = rs.getBoolean(3);
+ Long procId = rs.getLong(4);
+
+ result.add(new SqlQueryStat(q, new PGInterval(age), waiting, procId));
+ }
+
+ } finally {
+ rs.close();
+ }
+ return result;
+ }
+
+ /**
+ * Tablename der optinal als das Schema enthalten darf.
+ */
+ public static boolean removeColumn(Connection c, String tableName, String columnName) throws SQLException {
+
+ // Das eigentliche erstellen der neuen Spalte
+ String queryString = "ALTER TABLE " + tableName + " DROP COLUMN " + columnName;
+
+ // System.out.println(queryString);
+
+ int result = c.createStatement().executeUpdate(queryString);
+
+ if (result != 0) {
+ // JRegDBUtils.log.error(queryString + " returned not 0 = " +
+ // result);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Liefert die COLUMN-NAMES eines PKs einer Tabelle
+ *
+ * @param dbc
+ * Connection to Postgressql Database
+ * @param tableName
+ * darf Schemanamen enthalten.
+ *
+ * @return Primary Key. <code>NULL</code> if empty
+ */
+ public static String getPrimaryKey(Connection dbc, String tableName) throws SQLException {
+
+ String schema = "public";
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ Statement s = dbc.createStatement();
+ ResultSet rs = s
+ .executeQuery("select distinct(column_name) from INFORMATION_SCHEMA.KEY_COLUMN_USAGE a,INFORMATION_SCHEMA.TABLE_CONSTRAINTS b where constraint_type = 'PRIMARY KEY' and a.table_name='"
+ + tableName + "' and a.table_schema='" + schema + "';");
+
+ String pk = "";
+ try {
+
+ while (rs.next()) {
+ pk += rs.getString("column_name");
+ }
+
+ } finally {
+ rs.close();
+ }
+
+ if (pk.endsWith(","))
+ pk = pk.substring(0, pk.length() - 1);
+
+ return pk.isEmpty() ? null : pk;
+
+ }
+
+ /**
+ * Returns cardinality of column in table
+ */
+ public long getCardinality(Connection dbc, String tableName, String column) throws SQLException {
+ String sql = "select count( DISTINCT " + "(" + column + ")" + ") " + "from " + tableName;
+ ResultSet countRs = dbc.createStatement().executeQuery(sql);
+ try {
+ countRs.next();
+ return ((Number) countRs.getLong(1)).longValue();
+ } finally {
+ countRs.close();
+ }
+ }
+
+ public static boolean isIntColumn(Connection c, String tableName, String columnName) throws SQLException {
+ String schema = "public";
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ Statement s = c.createStatement();
+ ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
+ + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
+ try {
+
+ rs.next();
+ String typeDef = rs.getString(1);
+ Boolean isNumeric = false;
+ isNumeric |= typeDef.startsWith("numeric");
+
+ return isNumeric;
+ } finally {
+ rs.close();
+ }
+ }
+
+ /**
+ * Typischer Weise POSTGIS, wenn man sonst nichts anderen installiert hat.
+ */
+ public static boolean isUserDefinedColumn(Connection c, String tableName, String columnName) throws SQLException {
+
+ String schema = "public";
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ Statement s = c.createStatement();
+ ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
+ + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
+ rs.next();
+ String typeDef = rs.getString(1);
+ return typeDef.toUpperCase().startsWith("USER-DEFINED");
+ }
+
+ public static boolean isTextColumn(Connection c, String tableName, String columnName) throws SQLException {
+
+ String schema = "public";
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ Statement s = c.createStatement();
+ ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
+ + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
+ try {
+ rs.next();
+ String typeDef = rs.getString(1);
+ Boolean isText = false;
+ isText |= typeDef.startsWith("text");
+ isText |= typeDef.startsWith("character");
+
+ return isText;
+ } finally {
+ rs.close();
+ }
+ }
+
+ /**
+ * Creates a new Column.
+ *
+ * @param dbc
+ * @param tableName
+ * @param columnName
+ * @param colTypeName
+ * @param comment
+ * @return
+ * @throws SQLException
+ */
+ public static boolean addColumn(Connection dbc, String tableName, String columnName, String colTypeName,
+ String comment) throws SQLException {
+
+ if (dbc == null)
+ throw new IllegalStateException("Es besteht keine Datenbankverbindung!");
+
+ Statement s = dbc.createStatement();
+
+ if (existsColumn(dbc, tableName, columnName)) {
+ return false;
+ }
+
+ // Das eigentliche erstellen der neuen Spalte
+ String queryString = "ALTER TABLE " + tableName + " ADD " + columnName + " " + colTypeName;
+
+ // JRegDBUtils.log.debug(queryString);
+
+ int result = s.executeUpdate(queryString);
+
+ if (result != 0) {
+ return false;
+ }
+
+ if (comment != null && !comment.isEmpty()) {
+ queryString = "COMMENT ON COLUMN " + tableName + "." + columnName + " IS '" + comment + "';";
+ }
+
+ s.close();
+
+ return true;
+ }
+
+ /**
+ * Liefert alle Spalten einer Tabelle
+ */
+ public static ArrayList<String> getAllColumnsOf(Connection dbc, String tableName) throws SQLException {
+ String schema = "public";
+ if (tableName.contains(".")) {
+ final String[] split = tableName.split("\\.");
+ schema = split[0];
+ tableName = split[1];
+ }
+
+ ArrayList<String> cols = new ArrayList<String>();
+
+ // String tableName = PropertyUtils.getDbTableName(i);
+
+ String sql = "SELECT column_name FROM information_schema.COLUMNS WHERE TABLE_NAME = '" + tableName
+ + "' and TABLE_SCHEMA = '" + schema + "';";
+
+ ResultSet colsRs = dbc.createStatement().executeQuery(sql);
+ try {
+ while (colsRs.next())
+ cols.add(colsRs.getString(1));
+ } finally {
+ colsRs.close();
+ }
+ return cols;
+ }
+
+}
Property changes on: trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/PGUtil.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/SqlQueryStat.java (from rev 1818, trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java)
===================================================================
--- trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/SqlQueryStat.java 2012-01-14 20:45:15 UTC (rev 1819)
@@ -0,0 +1,63 @@
+package de.schmitzm.postgres;
+
+import java.sql.SQLException;
+
+import org.apache.log4j.Logger;
+import org.postgresql.util.PGInterval;
+
+/**
+ * Beschreibt eine laufende SQL Aktion.
+ *
+ * TODO schmitzm-pg
+ */
+public class SqlQueryStat {
+
+ final static Logger log = Logger.getLogger(SqlQueryStat.class);
+ private final boolean waiting;
+
+ public SqlQueryStat(String query, String interval, boolean waiting, Long procId) {
+ this.query = query;
+ this.waiting = waiting;
+ this.procId = procId;
+ PGInterval runningFor_;
+ try {
+ runningFor_ = new PGInterval(interval);
+ } catch (SQLException e) {
+ log.error(e);
+ runningFor_ = new PGInterval();
+ }
+ runningFor = runningFor_;
+ }
+
+ public SqlQueryStat(String query, PGInterval interval, boolean waiting, Long procId) {
+ this.query = query;
+ this.waiting = waiting;
+ this.procId = procId;
+ this.runningFor = interval;
+ }
+
+ public PGInterval getRunningFor() {
+ return runningFor;
+ }
+
+ public String getQuery() {
+ return query;
+ }
+
+ public boolean isWaiting() {
+ return waiting;
+ }
+
+ public Long getProcId() {
+ return procId;
+ }
+
+ /**
+ * Process-ID
+ */
+ private final Long procId;
+
+ private final PGInterval runningFor;
+ private final String query;
+
+}
Property changes on: trunk/schmitzm-db/src/main/java/de/schmitzm/postgres/SqlQueryStat.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/schmitzm-db/src/main/java/de/schmitzm/sql/SqlUtil.java (from rev 1818, trunk/schmitzm-db/src/main/java/sql/SqlUtil.java)
Property changes on: trunk/schmitzm-db/src/main/java/de/schmitzm/sql/SqlUtil.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/schmitzm-db/src/main/java/postgres/PGUtil.java
===================================================================
--- trunk/schmitzm-db/src/main/java/postgres/PGUtil.java 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/src/main/java/postgres/PGUtil.java 2012-01-14 20:45:15 UTC (rev 1819)
@@ -1,971 +0,0 @@
-package de.schmitzm.postgres;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import de.schmitzm.lang.LangUtil;
-
-/**
- * Hilfsmethoden für PostgreSQL. Die Dependency soll nur {@link Connection} sein. In Hibernate kann über #doWork eine
- * {@link Connection} erhalten werden.
- */
-public class PGUtil {
- static final Logger log = Logger.getLogger(PGUtil.class);
-
- /**
- * PostgreSQL Privilegien die per Grant einer Tabelle zugeordnet werden können.<br/>
- *
- * @see http://www.postgresql.org/docs/9.1/static/sql-grant.html
- */
- public enum Privileges {
- SELECT, INSERT, UPDATE, DELETE, REFERENCES, TEMPORARY, ALL_PRIVILEGES("ALL PRIVILEGES");
-
- String sql;
-
- Privileges() {
- this.sql = super.toString();
- }
-
- Privileges(String sql) {
- this.sql = sql;
- }
-
- @Override
- public String toString() {
- return this.sql;
- }
- }
-
- /**
- * Fügt Privilegien für eine Rolle einer Tabelle hinzu.
- *
- * @param tablename
- * Tabellennamen, optional mit "schema.tablename"
- * @param targetRole
- * Darf PUBLIC sein, oder Name einer ROLLE.
- * @param privileges
- * List der zuzuordnenden Privilegien
- * @throws SQLException
- */
- public static void grantPrivilegesOnTable(Connection c, String targetRole, String tablename,
- Privileges... privileges) throws SQLException {
- // GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
- String sql = "GRANT " + LangUtil.stringConcatWithSep(",", (Object[]) privileges) + " ON " + tablename + " TO "
- + targetRole;
- c.createStatement().executeUpdate(sql);
- }
-
- /**
- * Entfernt Privilegien für eine Rolle von einre Tabelle.
- *
- * @param tablename
- * Tabellennamen, optional mit "schema.tablename"
- * @param privileges
- * List der zuzuordnenden Privilegien
- * @throws SQLException
- */
- public static void revokePrivilegesOnTable(Connection c, String tablename, String targetRole,
- Privileges... privileges) throws SQLException {
- // GRANT SELECT, UPDATE, INSERT ON mytable TO admin;
- String sql = "REVOKE " + LangUtil.stringConcatWithSep(",", (Object[]) privileges) + " ON " + tablename
- + " FROM " + targetRole;
- c.createStatement().executeUpdate(sql);
- }
-
- /**
- * Erstellt eine neue Rolle
- *
- * @param rolename
- * Name der neuen Rolle
- * @param inhRoles
- * Rollen in denen die neue Rolle Mitglied ist
- */
- public static void createRole(Connection c, String rolename, String... inhRoles) throws SQLException {
- String sql = "CREATE ROLE " + rolename;
- c.createStatement().executeUpdate(sql);
- for (String inhRole : inhRoles)
- c.createStatement().executeUpdate("GRANT " + inhRole + " TO " + rolename);
- }
-
- /**
- * Erstellt eine neue Rolle, wenn diese noch nicht existiert.
- *
- * @param rolename
- * Name der neuen Rolle
- * @param inhRoles
- * Rollen in denen die neue Rolle Mitglied ist
- */
- public static void createRoleIfNotExists(Connection c, String rolename, String... inhRoles) throws SQLException {
- if (existsRole(c, rolename))
- return;
- createRole(c, rolename, inhRoles);
- }
-
- /**
- * Querys the <code>geometry_columns</code> table is part of every POSTGIS installation and must/should describe the
- * geometry columns and tables.
- */
- static public String[] getColumnsDescribedInGeometryColumnsTable(Statement s) {
- String[] columns = new String[0];
- try {
- ResultSet rs = s.executeQuery("SELECT f_table_name FROM geometry_columns;");
- try {
-
- while (rs.next()) {
- columns = LangUtil.extendArray(columns, rs.getString(1));
- }
- } finally {
- rs.close();
- }
- } catch (SQLException e) {
- log.error(e, e);
- }
-
- return columns;
-
- }
-
- /**
- * Creates or Updates
- *
- * @param tableName
- * @param geoColumnName
- * @param srid
- */
- @Deprecated
- // tut noch nicht
- public static void createOrUpdateGeometrysColumnsEntry(String tableName, String geoColumnName, int srid) {
-
- String createGeometryEntrySQL = "INSERT INTO geometry_columns (f_table_catalog, f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, \"type\") VALUES ( '', 'public', '"
- + tableName + "', '" + geoColumnName + "', 2, " + srid + ",'MULTIPOLYGON' ) LIMIT 1;";
- }
-
- // TODO isGeoColumn();
-
- /**
- * @param binding
- * Eine "einfache" Javaklasse, die in PG abgebildet werden soll.
- * @return einen PG-spezifischen Datentypenamen für einen Javatyp zurück, z.b. "double precision" für
- * <code>Double.class</code>
- */
- public static String getColTypeName(Class<?> binding) {
-
- if (binding.isAssignableFrom(Double.class)) {
- return "double precision"; // eg 'number' at oracle
- } else if (binding.isAssignableFrom(String.class)) {
- return "text";
- } else if (binding.isAssignableFrom(Integer.class)) {
- return "integer";
- } else if (binding.isAssignableFrom(Long.class)) {
- return "bigint";
- }
-
- throw new RuntimeException("DB Type mapping for " + binding + " not yet implemented.");
- }
-
- /**
- * Legt ein Schema an, wenn es vorher nicht existierte.
- *
- * @return <code>true</code> wenn das Schema neu angelegt wurde.
- */
- public static boolean createSchemaIfNotExists(Connection c, String schemaname) throws SQLException {
- if (!existsSchema(c, schemaname)) {
- c.createStatement().execute("create schema " + schemaname.toLowerCase());
- return true;
- }
- return false;
- }
-
- /**
- * Liefert <code>true</code> wenn ein Schema mit dem Namen in der PG Datenbank existiert.
- */
- public static boolean existsSchema(Connection c, String schemaname) throws SQLException {
- String sql = "select 1 from pg_catalog.pg_namespace where nspname = '" + schemaname.toLowerCase() + "'";
- ResultSet rs = c.createStatement().executeQuery(sql);
- try {
- return rs.next();
- } finally {
- rs.close();
- }
-
- }
-
- /**
- * Liefert eine Liste der Rollen in denen der Übergebenen USER (Login role) ist. <br/>
- * Tested with PG 8.4
- */
- public static List<String> listRolesForUser(Connection c, String username) throws SQLException {
- List<String> roles = new ArrayList<String>();
- String sql = "select rolname from pg_user join pg_auth_members on (pg_user.usesysid=pg_auth_members.member) join pg_roles on (pg_roles.oid=pg_auth_members.roleid) where pg_user.usename='"
- + username.toLowerCase() + "'";
- ResultSet rs = c.createStatement().executeQuery(sql);
- try {
- while (rs.next()) {
- roles.add(rs.getString(1));
- }
- } finally {
- rs.close();
- }
- return roles;
- }
-
- /**
- * Liefert alle Benutzer der DB zurück.
- *
- * @throws SQLException
- */
- public static List<String> listUsers(Connection c) throws SQLException {
- List<String> roles = new ArrayList<String>();
- ResultSet rs = c.createStatement().executeQuery("select * from pg_user");
- try {
- while (rs.next()) {
- roles.add(rs.getString(1));
- }
- } finally {
- rs.close();
- }
- return roles;
- }
-
- /**
- * Liste aller Tabellennamen in diesem Schema, ohne die Schemaangabe im Namen. (Also 'anreden' und nicht
- * 'public.anreden') <br/>
- * Tested with PG 8.4
- *
- * @param schemaname
- * if <code>null</code>, <code>public</code> is used.
- */
- public static List<String> listTablesInSchema(Connection c, String schemaname) throws SQLException {
- List<String> tables = new ArrayList<String>();
-
- String sql = "select tablename from pg_tables where schemaname = '" + schemaname.toLowerCase() + "'";
- ResultSet rs = c.createStatement().executeQuery(sql);
- try {
- while (rs.next()) {
- tables.add(rs.getString(1));
- }
- } finally {
- rs.close();
- }
- return tables;
- }
-
- /**
- * Liefert <code>true</code> wenn der Benutzername im DBMS Superuser ist.
- */
- public static boolean isSuperuser(Connection c, String username) throws SQLException {
- ResultSet rs = c.createStatement().executeQuery(
- "select usesuper from pg_user where usename = '" + username + "' and usesuper = true");
- try {
- if (rs.next()) {
- return true;
- }
- } finally {
- rs.close();
- }
- return false;
- }
-
- public static boolean existsRole(Connection c, String rolename) throws SQLException {
- String sql = "select count(1) from pg_roles where rolname = '" + rolename.toLowerCase() + "'";
- ResultSet rs = c.createStatement().executeQuery(sql);
- try {
- if (rs.next())
- return rs.getInt(1) > 0;
- } finally {
- rs.close();
- }
- return false;
- }
-
- public static void removeAllPrivilegesFrom(Connection c, String rolename, String tablename) throws SQLException {
- c.createStatement().executeUpdate(
- "revoke all on TABLE " + tablename.toLowerCase() + " from " + rolename.toLowerCase() + " cascade");
- }
-
- /**
- * Löscht eine Rolle wenn sie vorher existiert
- */
- public static void dropRoleIfExists(Connection c, String rolename) throws SQLException {
- c.createStatement().executeUpdate("drop role if exists " + rolename.toLowerCase());
- }
-
- /**
- * Löscht einen Trigger wenn er vorher existierte.
- *
- * @param c
- * @param triggerName
- * @param tableName
- */
- public static void dropTriggerIfExists(Connection c, String triggerName, String tableName) throws SQLException {
- c.createStatement().executeUpdate("drop TRIGGER if exists " + triggerName.toLowerCase() + " ON " + tableName);
- }
-
- /**
- *
- * @param c
- * @param name
- * z.B.: keckformel wird dann zu keckformel()
- * @param plCommands
- * z.B.
- * <code>NEW.kpk_kreis = NEW.risiko_soz+NEW.risiko_emo+NEW.risiko_moti +NEW.risiko_spr+NEW.risiko_wohl;</code>
- * OHNE <code>RETURN NEW</code>, das wird automatisch angehangen.
- * @throws SQLException
- */
- public static void createOrReplaceTriggerFunction(Connection c, String name, String plCommands) throws SQLException {
- // System.err.println(plCommands);
-
- // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name
- // + "$\nBEGIN\n?\nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
- // PreparedStatement ps = c.prepareStatement(sql);
- // ps.setString(0, plCommands);
- // ps.executeUpdate();
-
- // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name + "$\nBEGIN\n "
- // + plCommands + " \nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
- // c.createStatement().executeUpdate(sql);
-
- createOrReplaceFunction(c, name, null, "TRIGGER", null, plCommands + "\nRETURN NEW");
- }
-
- /**
- *
- * @param c
- * @param name
- * z.B.: keckformel wird dann zu keckformel()
- * @param parameters
- * Parameter der Funcktion, kann <code>null</code> sein.
- * @param returns
- * z.B. <code>TRIGGER</code> oder <code>SETOF bigint</code> oder "void"
- * @param declare
- * Declare block oder <code>null</code>
- * @param plCommands
- * z.B. NEW.kpk_kreis = NEW.risiko_soz+NEW.risiko_emo+NEW.risiko_moti +NEW.risiko_spr+NEW.risiko_wohl;
- */
- public static void createOrReplaceFunction(Connection c, String name, String parameters, String returns,
- String declare, String plCommands) throws SQLException {
- // System.err.println(plCommands);
-
- // String sql = "CREATE OR REPLACE FUNCTION " + name + "()" + " RETURNS trigger AS $" + name
- // + "$\nBEGIN\n?\nRETURN NEW;" + "\nEND;\n$" + name + "$ LANGUAGE 'plpgsql'";
- // PreparedStatement ps = c.prepareStatement(sql);
- // ps.setString(0, plCommands);
- // ps.executeUpdate();
-
- parameters = LangUtil.removeWhitespacesToEmpty(parameters);
- declare = LangUtil.removeWhitespacesToEmpty(declare);
-
- String sql = "CREATE OR REPLACE FUNCTION " + name + "(" + parameters + ")" + " RETURNS " + returns + " AS $$\n"
- + "DECLARE\n" + declare + "\n" + "BEGIN\n " + plCommands + ";" + "\nEND;\n$$ LANGUAGE 'plpgsql'";
- c.createStatement().executeUpdate(sql);
- }
-
- /**
- * Erstellt einen <code>FOR EACH ROW EXECUTE PROCEDURE</code> trigger für eine Tabelle
- *
- * @param c
- * @param triggerName
- * @param type
- * z.B. "BEFORE INSERT OR UPDATE"
- * @param tableName
- * @param plCommands
- * PSQL commands, e.g.<br/>
- * <code>
- IF ((TG_OP = 'UPDATE') or (TG_OP = 'INSERT') ) THEN
- INSERT INTO workqueue values (NEW.id);
- RETURN NEW;
- END IF;
- </code>
- */
- public static void createOrRecreateTrigger(Connection c, String triggerName, String type, String tableName,
- String plCommands) throws SQLException {
- dropTriggerIfExists(c, triggerName, tableName);
- createOrReplaceTriggerFunction(c, triggerName + "_fn", plCommands);
- c.createStatement().executeUpdate(
- "CREATE TRIGGER " + triggerName + " " + type + " ON " + tableName + " FOR EACH ROW EXECUTE PROCEDURE "
- + triggerName + "_fn" + "()");
- }
-
- /**
- * @param tableName
- * e.g. 'inseratabfragen_kvps'
- * @param columns
- * e.g. 'inseratabfrage_id'
- * @param idxNamePostfix
- * e.g. 'idx1'
- * @param unique
- * <code>true</code> if the columns are unique. A UNIQUE INDEX will be created.
- */
- public static void addIndex(Connection c, final String tableName, final String columns, String idxPostfix,
- final boolean unique) throws SQLException {
- addIndex(c, tableName, columns, idxPostfix, unique, null, null, false, null);
- }
-
- /**
- * Liefert eine Liste aller Indexnamen die für eine Tabelle existieren. Der Tabellenname wird mit <code>like</code>
- * verglichen, darf also <code>%</code> enthalten.<br/>
- * Achtung: Diese abfrage ist nicht Schema-Spezifisch. Eine schema. Angabe vor dem tabellennamen wird automatisch
- * entfernt.
- */
- public static List<String> listIndexesForTable(Connection c, String tableName) throws SQLException {
- Statement s = c.createStatement();
-
- if (tableName.contains("."))
- tableName = tableName.substring(tableName.indexOf(".") + 1, tableName.length());
-
- List<String> idxes = new ArrayList<String>();
-
- // , array_to_string(array_agg(a.attname), ', ') as column_names
- String sql = "select t.relname as table_name, i.relname as index_name from pg_class t, pg_class i, pg_index ix, pg_attribute a where t.oid = ix.indrelid and i.oid = ix.indexrelid and a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relkind = 'r' and t.relname like '"
- + tableName + "' group by t.relname, i.relname order by t.relname, i.relname";
-
- ResultSet rs = s.executeQuery(sql);
- try {
- while (rs.next()) {
- idxes.add(rs.getString(2));
- }
- } finally {
- rs.close();
- }
-
- return idxes;
-
- }
-
- /**
- * @param tableName
- * e.g. 'inseratabfragen_kvps'
- * @param columns
- * e.g. 'inseratabfrage_id'
- * @param idxNamePostfix
- * e.g. 'idx1'
- * @param unique
- * <code>true</code> if the columns are unique. A UNIQUE INDEX will be created.
- * @param tablespace
- * <code>null</code> oder der name des tablespace in dem der Index liegen soll.
- * @param type
- * <code>null</code> für DB default oder "hash" oder "btree" oder "gin" etc...
- * @param forceRecreationIfExistsAlready
- * wenn <code>true</code> dann werden der Index vorher gedroppt falls er exisitert.
- * @param fillFactor
- * Wert von >0. -> 1. Bei .5 wird für den Index doppelt so viel Platz reserviert wie aktuell benötig, um
- * auf weiteres Wachstum der Tabelle ohne Indexfragmentierung reagieren zu können.
- */
- public static void addIndex(Connection c, final String tableName, final String columns, String idxPostfix,
- final boolean unique, String tablespace, String type, boolean forceRecreationIfExistsAlready,
- Double fillFactor) throws SQLException {
- String idxNameWithDot = tableName + "_" + idxPostfix;
- final String idxName = idxNameWithDot.replace(".", "_");
-
- // Wenn der Tablename ein Schema mit "schema.name" enthält, dann liefert
- // listIndexesForTable hier ein schema_table im Index-Namen zurück. Der
- // "." wird also zu einem "_"
- for (String existIdxName : listIndexesForTable(c, tableName)) {
- if (existIdxName.equalsIgnoreCase(idxName.replaceFirst("\\.", "_"))) {
- // Existiert bereits.
-
- if (!forceRecreationIfExistsAlready)
- return;
-
- log.info("Aufgrund von forceRecreationIfExistsAlready=true wird der Index " + idxNameWithDot
- + " jetzt gedroppt.");
-
- Statement s = c.createStatement();
-
- // Hier die Schreibweise mit . für schematrennung verwenden
- final String queryString = "DROP INDEX " + idxNameWithDot;
- try {
- s.execute(queryString);
- c.commit();
- log.debug("Index dropped: " + queryString);
- } catch (SQLException e) {
- c.rollback();
- Throwable cause = e;
- if (e.getCause() != null)
- cause = e.getCause();
-
- // keine Ausgabe bei: already EXISTs, EXISTiert
- // bereits,
- // ...
- // Ex abfangen, wenn IDX schon existiert
-
- String msg = cause.getMessage();
- log.error(e.getLocalizedMessage(), e);
- return;
- }
-
- break;
-
- }
- }
-
- Statement s = c.createStatement();
-
- if (fillFactor != null && (fillFactor <= 0. || fillFactor > 1.))
- throw new IllegalArgumentException("fillFactor muss großer 0 und kleinergleich 1 sein.");
-
- String sqlFillFactor = "";
- if (fillFactor != null)
- sqlFillFactor = " WITH (FILLFACTOR=" + (int) (fillFactor * 100) + ") ";
-
- String sqlTableSpace = (tablespace == null || tablespace.equalsIgnoreCase("null") || !existsTablespace(c, tableName)) ? "" : " TABLESPACE "
- + tablespace;
-
-
-
- String sqlUsing = type == null ? "" : " USING " + type;
-
- final String queryString = "CREATE " + (unique ? "UNIQUE " : "") + "INDEX " + idxName + " ON " + tableName
- + sqlUsing + " (" + columns + ") " + sqlFillFactor + sqlTableSpace;
- try {
- s.execute(queryString);
- c.commit();
- log.info("Neuen Index erstellt: " + queryString);
- } catch (SQLException e) {
- c.rollback();
- Throwable cause = e;
- if (e.getCause() != null)
- cause = e.getCause();
-
- // keine Ausgabe bei: already EXISTs, EXISTiert
- // bereits,
- // ...
- // Ex abfangen, wenn IDX schon existiert
-
- String msg = cause.getMessage();
- if (msg.endsWith("already exists") || msg.endsWith("existiert bereits")) {
- // TO NOTHING, IDX already exists
- log.info("Index existierte bereits, nicht neuerstellt: " + queryString);
- } else
- log.error(e.getLocalizedMessage(), e);
-
- }
-
- }
-
- /**
- * Liefert <code>true</code> wenn ein tablespace mit dem Namen existiert.
- * @throws SQLException
- */
- private static boolean existsTablespace(Connection c, String spaceName) throws SQLException {
-
- // SELECT count(1) FROM pg_tablespace where spcname = 'spcname';
- String stmtSql = "SELECT COUNT(*) FROM pg_tablespace where spcname = '"+spaceName+"'";
-
- PreparedStatement stmt = c.prepareStatement(stmtSql);
- stmt.execute();
-
- ResultSet result = stmt.getResultSet();
- try {
- int count = 0;
- if (result.next())
- count = result.getInt(1);
-
- return count > 0;
- } finally {
- result.close();
- stmt.close();
- }
-
- }
-
- /**
- * Fügt einen Benutzer zu einer Rolle hinzu. Wenn der benutzer bereits in der Rolle enthalten ist, wird keine
- * Exception geschmisssen.
- *
- * @throws SQLException
- */
- public static void grantRoleToUser(Connection c, String rolename, String username) throws SQLException {
- c.createStatement().executeUpdate("GRANT " + rolename + " TO " + username);
- }
-
- /**
- * Der : (Doppelpunkt) hat in PSQL eine besondere Bedeutung. Er wind mit dieser methode escaped. Diese Methode
- * sollte mit <code>like E'"+PGUtil.escape(...)+"'</code> verwendet werden.
- */
- public static String escape(String key) {
- key = key.replaceAll(":", "\\:");
- return key;
- }
-
- /**
- * Liefert die Anzahl der offenen Sessions zur Datenbank.
- *
- * @param c
- * DB-Verbindung
- * @param dbName
- * Name der Datenbank fuer die die Sessions gezaehlt werden (kann {@code null} sein)
- * @param userName
- * Name des Users fuer den die Sessions gezaehlt werden (kann {@code null} sein)
- */
- public static int getOpenSessionCount(Connection c, String dbName, String userName) throws SQLException {
- return getOpenSessionCount(c, dbName, userName, null);
- }
-
- /**
- * Liefert die Anzahl der offenen Sessions zur Datenbank.
- *
- * @param c
- * DB-Verbindung
- * @param dbName
- * Name der Datenbank fuer die die Sessions gezaehlt werden (kann {@code null} sein)
- * @param userName
- * Name des Users fuer den die Sessions gezaehlt werden (kann {@code null} sein)
- * @param queryLike
- * like-Beindung auf die Query die in der Session ausgeführt wird, oder <code>null</code>
- */
- public static int getOpenSessionCount(Connection c, String dbName, String userName, String queryLike)
- throws SQLException {
- String stmtSql = "SELECT COUNT(*) FROM pg_stat_activity WHERE TRUE";
-
- if (dbName != null)
- stmtSql += " AND datname = ?";
- if (userName != null)
- stmtSql += " AND usename = ?";
- if (queryLike != null) {
- stmtSql += " AND current_query like '" + queryLike + "'";
- }
-
- PreparedStatement stmt = c.prepareStatement(stmtSql);
- if (dbName != null)
- stmt.setString(1, dbName);
- if (userName != null)
- stmt.setString(2, userName);
- stmt.execute();
-
- ResultSet result = stmt.getResultSet();
- try {
- int count = 0;
- if (result.next())
- count = result.getInt(1);
-
- return count;
- } finally {
- result.close();
- stmt.close();
- }
- }
-
- /**
- * Liefert <code>true</code> wenn eine Spalte mit dem Namen in der angegebenen Tabelle existiert. Die Tablle darf
- * optional mit "schema." prefixiert werden.
- */
- public static boolean existsColumn(Connection c, String tableName, String columnName) throws SQLException {
-
- String schema = "public";
-
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- ResultSet nativeCheckExistsColumnQuery = c.createStatement().executeQuery(
- "SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME = '" + columnName.toLowerCase()
- + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
- return nativeCheckExistsColumnQuery.next();
- }
-
- /**
- * Existiert ein relationsname als View?
- *
- * @param viewName
- * Darf eine Schemaangabe mit . Trenner enthalten.
- * @throws SQLException
- */
- public static boolean existsView(Connection c, String viewName) throws SQLException {
-
- String schema = "public";
-
- if (viewName.contains(".")) {
- final String[] split = viewName.split("\\.");
- schema = split[0];
- viewName = split[1];
- }
-
- final String checkView = "SELECT * FROM information_schema.VIEWS where table_schema = '" + schema
- + "' and table_name = '" + viewName + "' LIMIT 1";
- ResultSet rs = c.createStatement().executeQuery(checkView);
-
- try {
- return rs.next();
- } finally {
- rs.close();
- }
- }
-
- public static void dropViewIfExists(Connection c, String viewName) throws SQLException {
- final String dropView = "DROP VIEW IF EXISTS " + viewName;
- c.createStatement().executeUpdate(dropView);
- }
-
- /**
- * Liefert eine Liste der aktuell laufenden Queries und ihrere Laufzeiten zurück. Der 2. Teil der Rückgabepaare ist
- * ein String der einem PG Interval entspricht. Dieses kann mit der Klasse PGInterval geparst werden.<br/>
- *
- * @param datName
- * <code>null</code> oder der Datenbankname, auf den die Abfrage gefiltert werden soll.
- *
- * @param minSecondsRunning
- * <code>null</code> oder die zurückgegebenen Anfragen müssen mindestens soviele Sekunden schon laufen.
- */
- static public List<String[]> listQueries(Connection c, String datName, Integer minSecondsRunning)
- throws SQLException {
- ArrayList<String[]> result = new ArrayList<String[]>();
-
- String where = "where current_query not like '%IDLE%' ";
-
- if (datName != null)
- where += " and datname like '" + datName + "'";
-
- if (minSecondsRunning != null) {
- if (minSecondsRunning < 0)
- throw new IllegalStateException();
-
- where += " and age (now(),query_start) >= interval '" + minSecondsRunning + " second' ";
- }
-
- final String sql = "select current_query, age (now(),query_start) as qage, waiting, procpid from pg_stat_activity "
- + where + " order by qage desc";
- ResultSet rs = c.createStatement().executeQuery(sql);
-
- try {
- while (rs.next()) {
- String q = rs.getString(1);
- String since = rs.getString(2);
- String waiting = rs.getString(3);
- String waiting = rs.getString(3);
-
- result.add(new String[] { q, since, waiting });
- }
-
- } finally {
- rs.close();
- }
- return result;
- }
-
- /**
- * Tablename der optinal als das Schema enthalten darf.
- */
- public static boolean removeColumn(Connection c, String tableName, String columnName) throws SQLException {
-
- // Das eigentliche erstellen der neuen Spalte
- String queryString = "ALTER TABLE " + tableName + " DROP COLUMN " + columnName;
-
- // System.out.println(queryString);
-
- int result = c.createStatement().executeUpdate(queryString);
-
- if (result != 0) {
- // JRegDBUtils.log.error(queryString + " returned not 0 = " +
- // result);
- return false;
- }
- return true;
- }
-
- /**
- * Liefert die COLUMN-NAMES eines PKs einer Tabelle
- *
- * @param dbc
- * Connection to Postgressql Database
- * @param tableName
- * darf Schemanamen enthalten.
- *
- * @return Primary Key. <code>NULL</code> if empty
- */
- public static String getPrimaryKey(Connection dbc, String tableName) throws SQLException {
-
- String schema = "public";
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- Statement s = dbc.createStatement();
- ResultSet rs = s
- .executeQuery("select distinct(column_name) from INFORMATION_SCHEMA.KEY_COLUMN_USAGE a,INFORMATION_SCHEMA.TABLE_CONSTRAINTS b where constraint_type = 'PRIMARY KEY' and a.table_name='"
- + tableName + "' and a.table_schema='" + schema + "';");
-
- String pk = "";
- try {
-
- while (rs.next()) {
- pk += rs.getString("column_name");
- }
-
- } finally {
- rs.close();
- }
-
- if (pk.endsWith(","))
- pk = pk.substring(0, pk.length() - 1);
-
- return pk.isEmpty() ? null : pk;
-
- }
-
- /**
- * Returns cardinality of column in table
- */
- public long getCardinality(Connection dbc, String tableName, String column) throws SQLException {
- String sql = "select count( DISTINCT " + "(" + column + ")" + ") " + "from " + tableName;
- ResultSet countRs = dbc.createStatement().executeQuery(sql);
- try {
- countRs.next();
- return ((Number) countRs.getLong(1)).longValue();
- } finally {
- countRs.close();
- }
- }
-
- public static boolean isIntColumn(Connection c, String tableName, String columnName) throws SQLException {
- String schema = "public";
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- Statement s = c.createStatement();
- ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
- + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
- try {
-
- rs.next();
- String typeDef = rs.getString(1);
- Boolean isNumeric = false;
- isNumeric |= typeDef.startsWith("numeric");
-
- return isNumeric;
- } finally {
- rs.close();
- }
- }
-
- /**
- * Typischer Weise POSTGIS, wenn man sonst nichts anderen installiert hat.
- */
- public static boolean isUserDefinedColumn(Connection c, String tableName, String columnName) throws SQLException {
-
- String schema = "public";
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- Statement s = c.createStatement();
- ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
- + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
- rs.next();
- String typeDef = rs.getString(1);
- return typeDef.toUpperCase().startsWith("USER-DEFINED");
- }
-
- public static boolean isTextColumn(Connection c, String tableName, String columnName) throws SQLException {
-
- String schema = "public";
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- Statement s = c.createStatement();
- ResultSet rs = s.executeQuery("SELECT data_type FROM information_schema.COLUMNS WHERE COLUMN_NAME = '"
- + columnName.toLowerCase() + "' AND TABLE_NAME='" + tableName + "' AND TABLE_SCHEMA='" + schema + "';");
- try {
- rs.next();
- String typeDef = rs.getString(1);
- Boolean isText = false;
- isText |= typeDef.startsWith("text");
- isText |= typeDef.startsWith("character");
-
- return isText;
- } finally {
- rs.close();
- }
- }
-
- /**
- * Creates a new Column.
- *
- * @param dbc
- * @param tableName
- * @param columnName
- * @param colTypeName
- * @param comment
- * @return
- * @throws SQLException
- */
- public static boolean addColumn(Connection dbc, String tableName, String columnName, String colTypeName,
- String comment) throws SQLException {
-
- if (dbc == null)
- throw new IllegalStateException("Es besteht keine Datenbankverbindung!");
-
- Statement s = dbc.createStatement();
-
- if (existsColumn(dbc, tableName, columnName)) {
- return false;
- }
-
- // Das eigentliche erstellen der neuen Spalte
- String queryString = "ALTER TABLE " + tableName + " ADD " + columnName + " " + colTypeName;
-
- // JRegDBUtils.log.debug(queryString);
-
- int result = s.executeUpdate(queryString);
-
- if (result != 0) {
- return false;
- }
-
- if (comment != null && !comment.isEmpty()) {
- queryString = "COMMENT ON COLUMN " + tableName + "." + columnName + " IS '" + comment + "';";
- }
-
- s.close();
-
- return true;
- }
-
- /**
- * Liefert alle Spalten einer Tabelle
- */
- public static ArrayList<String> getAllColumnsOf(Connection dbc, String tableName) throws SQLException {
- String schema = "public";
- if (tableName.contains(".")) {
- final String[] split = tableName.split("\\.");
- schema = split[0];
- tableName = split[1];
- }
-
- ArrayList<String> cols = new ArrayList<String>();
-
- // String tableName = PropertyUtils.getDbTableName(i);
-
- String sql = "SELECT column_name FROM information_schema.COLUMNS WHERE TABLE_NAME = '" + tableName
- + "' and TABLE_SCHEMA = '" + schema + "';";
-
- ResultSet colsRs = dbc.createStatement().executeQuery(sql);
- try {
- while (colsRs.next())
- cols.add(colsRs.getString(1));
- } finally {
- colsRs.close();
- }
- return cols;
- }
-
-}
Deleted: trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java
===================================================================
--- trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/src/main/java/postgres/SqlQueryStat.java 2012-01-14 20:45:15 UTC (rev 1819)
@@ -1,59 +0,0 @@
-package de.schmitzm.postgres;
-
-import java.sql.SQLException;
-
-import org.apache.log4j.Logger;
-import org.postgresql.util.PGInterval;
-
-/**
- * Beschreibt eine laufende SQL Aktion.
- *
- * TODO schmitzm-pg
- */
-public class SqlQueryStat {
-
- final static Logger log = Logger.getLogger(SqlQueryStat.class);
- private final boolean waiting;
-
- public SqlQueryStat(String query, String interval, boolean waiting, Long procId) {
- this.query = query;
- this.waiting = waiting;
- this.procId = procId;
- PGInterval runningFor_;
- try {
- runningFor_ = new PGInterval(interval);
- } catch (SQLException e) {
- log.error(e);
- runningFor_ = new PGInterval();
- }
- runningFor = runningFor_;
- }
-
- public PGInterval getRunningFor() {
- return runningFor;
- }
-
- public String getQuery() {
- return query;
- }
-
- public boolean isWaiting() {
- return waiting;
- }
-
- public Long getProcId() {
- return procId;
- }
-
- public void setProcId(Long procId) {
- this.procId = procId;
- }
-
- private final PGInterval runningFor;
- private final String query;
-
- /**
- * Process-ID
- */
- private final Long procId;
-}
Deleted: trunk/schmitzm-db/src/main/java/sql/SqlUtil.java
===================================================================
--- trunk/schmitzm-db/src/main/java/sql/SqlUtil.java 2012-01-14 20:38:46 UTC (rev 1818)
+++ trunk/schmitzm-db/src/main/java/sql/SqlUtil.java 2012-01-14 20:45:15 UTC (rev 1819)
@@ -1,61 +0,0 @@
-package de.schmitzm.sql;
-
-/**
- * Utilityklasse mit statisch Methoden für SQL.
- */
-public class SqlUtil {
-
- /**
- * VZ steht füer VergleichsZustände un beschreibt was beim vergleich zweier
- * attribute (.z.b. Hausnummer) alles rauskommen kann, wenn NULL gesondert
- * betrachtet wird.
- */
- public enum VZ {
- GLEICH, NULL1, NULL12, NULL2, UNGLEICH;
-
- /**
- * Drückt diesen Vergleichszustand als SQL aus.
- */
- public String toSql(String colName1, String colName2) {
-
- switch (this) {
- /**
- * Beide column haben den selben wert
- */
- case GLEICH:
- return "( (" + colName1 + " IS NOT NULL) AND (" + colName2
- + " IS NOT NULL) AND (" + colName1 + " LIKE "
- + colName2 + ") )";
- /**
- * Beide column sind nicht null und haben nicht den selben wert
- */
- case UNGLEICH:
- return "( (" + colName1 + " IS NOT NULL) AND (" + colName2
- + " IS NOT NULL) AND (NOT " + colName1 + " LIKE "
- + colName2 + ") )";
- /**
- * die erste col is null, die zweite nicht
- */
- case NULL1:
- return "( (" + colName1 + " IS NOT NULL) AND (" + colName2
- + " IS NULL) )";
- /**
- * die zweite col is null, die erste nicht
- */
- case NULL2:
- return "( (" + colName1 + " IS NOT NULL) AND (" + colName2
- + " IS NULL) )";
- /**
- * beide col sind null
- */
- case NULL12:
- return "( (" + colName1 + " IS NULL) AND (" + colName2
- + " IS NULL) )";
- }
-
- throw new IllegalStateException("Kann " + this
- + " nicht in SQL convertieren");
- }
- }
-
-}
\ No newline at end of file
More information about the Schmitzm-commits
mailing list