/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.jdbc.sql;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.Normalizer;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.lib.jdbc.DelegatingConnection;
import org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement;
import org.apache.openjpa.lib.jdbc.ReportingSQLException;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.StoreException;
import org.postgresql.PGConnection;
import org.postgresql.largeobject.LargeObject;
import org.postgresql.largeobject.LargeObjectManager;

/**
 * Dictionary for PostgreSQL.
 */
public class PostgresDictionary extends DBDictionary {

    private static final Localizer _loc = Localizer.forPackage(PostgresDictionary.class);


    private Method dbcpGetDelegate;
    private Method connectionUnwrap;

    protected Set<String> _timestampTypes = new HashSet<>();


    /**
     * SQL statement to load all sequence schema,name pairs from all schemas.
     */
    public String allSequencesSQL = "SELECT NULL AS SEQUENCE_SCHEMA, relname " +
        "AS SEQUENCE_NAME FROM pg_class WHERE relkind='S'";

    /**
     * SQL statement to load schema,name pairs for all sequences with a
     * certain name from all schemas.
     */
    public String namedSequencesFromAllSchemasSQL = "SELECT NULL AS " +
        "SEQUENCE_SCHEMA, relname AS SEQUENCE_NAME FROM pg_class " +
        "WHERE relkind='S' AND relname = ?";

    /**
     * SQL statement to load schema,name pairs from a named schema.
     */
    public String allSequencesFromOneSchemaSQL = "SELECT NULL AS " +
        "SEQUENCE_SCHEMA, relname AS SEQUENCE_NAME FROM pg_class, " +
        "pg_namespace WHERE relkind='S' AND pg_class.relnamespace = " +
        "pg_namespace.oid AND nspname = ?";

    /**
     * SQL statement to load a sequence's schema,name pair from one schema.
     */
    public String namedSequenceFromOneSchemaSQL = "SELECT NULL AS " +
        "SEQUENCE_SCHEMA, relname AS SEQUENCE_NAME FROM pg_class, " +
        "pg_namespace WHERE relkind='S' AND pg_class.relnamespace = " +
        "pg_namespace.oid AND relname = ? AND nspname = ?";

    /**
     * Some Postgres drivers do not support the {@link Statement#setFetchSize}
     * method.
     */
    public boolean supportsSetFetchSize = true;

    /**
     * Statement used to determine whether a sequence is owned.  Owned
     * sequences are managed by the database and are considered system
     * sequences.
     * parm 1: '<table_name.schema_name>'
     * parm 2: '<column_name>'
     */
    public String isOwnedSequenceSQL = "SELECT pg_get_serial_sequence(?, ?)";


    public PostgresDictionary() {
        platform = "PostgreSQL";
        validationSQL = "SELECT NOW()";
        datePrecision = MICRO;
        supportsAlterTableWithDropColumn = false;
        supportsDeferredConstraints = true;
        supportsSelectStartIndex = true;
        supportsSelectEndIndex = true;

        maxTableNameLength = 63;
        maxColumnNameLength = 63;
        maxIndexNameLength = 63;
        maxConstraintNameLength = 63;
        maxAutoAssignNameLength = 63;
        schemaCase = SCHEMA_CASE_LOWER;
        rangePosition = RANGE_POST_LOCK;
        requiresAliasForSubselect = true;
        allowsAliasInBulkClause = false;

        // single-quote escape will result in SELECT CURVAL('mysequence')
        lastGeneratedKeyQuery = "SELECT CURRVAL(''{1}_{0}_seq'')";
        supportsAutoAssign = true;
        autoAssignTypeName = "BIGSERIAL";
        nextSequenceQuery = "SELECT NEXTVAL(''{0}'')";

        useGetBytesForBlobs = true;
        useSetBytesForBlobs = true;
        useGetStringForClobs = true;
        useSetStringForClobs = true;
        bitTypeName = "BOOL";
        smallintTypeName = "SMALLINT";
        realTypeName = "FLOAT4";
        tinyintTypeName = "SMALLINT";
        binaryTypeName = "BYTEA";
        blobTypeName = "BYTEA";
        longVarbinaryTypeName = "BYTEA";
        varbinaryTypeName = "BYTEA";
        clobTypeName = "TEXT";
        longVarcharTypeName = "TEXT";
        doubleTypeName = "DOUBLE PRECISION";
        timestampTypeName = "TIMESTAMP";
        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
            "BOOL", "BYTEA", "NAME", "INT8", "INT2", "INT2VECTOR", "INT4",
            "REGPROC", "TEXT", "OID", "TID", "XID", "CID", "OIDVECTOR",
            "SET", "FLOAT4", "FLOAT8", "ABSTIME", "RELTIME", "TINTERVAL",
            "MONEY",
        }));
        booleanRepresentation = BooleanRepresentationFactory.BOOLEAN;

        supportsLockingWithDistinctClause = false;
        supportsLockingWithOuterJoin = false;

        reservedWordSet.addAll(Arrays.asList(new String[]{
            "ABORT", "ACL", "AGGREGATE", "APPEND", "ARCHIVE", "ARCH_STORE",
            "BACKWARD", "BINARY", "CHANGE", "CLUSTER", "COPY", "DATABASE",
            "DELIMITER", "DELIMITERS", "DO", "EXPLAIN", "EXTEND",
            "FORWARD", "HEAVY", "INDEX", "INHERITS", "ISNULL", "LIGHT",
            "LISTEN", "LOAD", "MERGE", "NOTHING", "NOTIFY", "NOTNULL",
            "OID", "OIDS", "PURGE", "RECIPE", "RENAME", "REPLACE",
            "RETRIEVE", "RETURNS", "RULE", "SETOF", "STDIN", "STDOUT",
            "STORE", "VACUUM", "VERBOSE", "VERSION",
        }));

        // reservedWordSet subset that CANNOT be used as valid column names
        // (i.e., without surrounding them with double-quotes)
        // generated at 2021-05-03T10:44:58.562 via org.apache.openjpa.reservedwords.ReservedWordsIT
        invalidColumnWordSet.addAll(Arrays.asList(new String[] {
            "ALL", "ANALYSE", "ANALYZE", "AND", "ANY", "ARRAY", "AS", "ASC", "ASYMMETRIC", "AUTHORIZATION", "BINARY", "BOTH",
            "CASE", "CAST", "CHECK", "COLLATE", "COLLATION", "COLUMN", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_ROLE",
            "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "DEFAULT", "DEFERRABLE", "DESC", "DISTINCT", "DO", "ELSE",
            "END", "END-EXEC", "EXCEPT", "FALSE", "FETCH", "FOR", "FOREIGN", "FREEZE", "FROM", "FULL", "GRANT", "GROUP", "HAVING",
            "ILIKE", "IN", "INITIALLY", "INNER", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "LATERAL", "LEADING", "LEFT",
            "LIKE", "LIMIT", "LOCALTIME", "LOCALTIMESTAMP", "NATURAL", "NOT", "NOTNULL", "NULL", "OFFSET", "ON", "ONLY", "OR",
            "ORDER", "OUTER", "OVERLAPS", "PLACING", "PRIMARY", "REFERENCES", "RIGHT", "SELECT", "SESSION_USER", "SIMILAR",
            "SOME", "SYMMETRIC", "TABLE", "TABLESAMPLE", "THEN", "TO", "TRAILING", "TRUE", "UNION", "UNIQUE", "USER", "USING",
            "VERBOSE", "WHEN", "WHERE", "WINDOW", "WITH",
            // end generated.
            // The following keywords used to be defined as reserved words in the past, but now seem to work
            // we still add them for compat reasons
            "BETWEEN",
        }));

        _timestampTypes.add("ABSTIME");
        _timestampTypes.add("TIMESTAMP");
        _timestampTypes.add(timestampTypeName.toUpperCase(Locale.ENGLISH)); // handle user configured timestamp types.

        indexPhysicalForeignKeys = true; // PostgreSQL does not automatically create an index for a foreign key so we will

        // PostgreSQL requires to escape search strings
        requiresSearchStringEscapeForLike = true;
    }



    @Override
    public Date getDate(ResultSet rs, int column)
        throws SQLException {
        try {
            return super.getDate(rs, column);
        } catch (StringIndexOutOfBoundsException sioobe) {
            // there is a bug in some versions of the postgres JDBC
            // driver such that a date with not enough numbers in it
            // will throw a parsing exception: this tries to work
            // around it. The bug only occurs when there is a trailing
            // millisecond missing from the end. E.g., when the date is
            // like:
            // 2066-10-19 22:08:32.83
            // rather than what the driver expects:
            // 2066-10-19 22:08:32.830
            String dateStr = rs.getString(column);
            SimpleDateFormat fmt = new SimpleDateFormat(
                "yyyy-MM-dd hh:mm:ss.SS");
            try {
                return fmt.parse(dateStr);
            } catch (ParseException pe) {
                throw new SQLException(pe.toString());
            }
        }
    }

    @Override
    public byte getByte(ResultSet rs, int column)
        throws SQLException {
        // postgres does not perform automatic conversions, so attempting to
        // get a whole number out of a decimal will throw an exception.
        // fall back to performing manual conversion if the initial get fails
        try {
            return super.getByte(rs, column);
        } catch (SQLException sqle) {
            return super.getBigDecimal(rs, column).byteValue();
        }
    }

    @Override
    public short getShort(ResultSet rs, int column)
        throws SQLException {
        // postgres does not perform automatic conversions, so attempting to
        // get a whole number out of a decimal will throw an exception.
        // fall back to performing manual conversion if the initial get fails
        try {
            return super.getShort(rs, column);
        } catch (SQLException sqle) {
            return super.getBigDecimal(rs, column).shortValue();
        }
    }

    @Override
    public int getInt(ResultSet rs, int column)
        throws SQLException {
        // postgres does not perform automatic conversions, so attempting to
        // get a whole number out of a decimal will throw an exception.
        // fall back to performing manual conversion if the initial get fails
        try {
            return super.getInt(rs, column);
        } catch (SQLException sqle) {
            return super.getBigDecimal(rs, column).intValue();
        }
    }

    @Override
    public long getLong(ResultSet rs, int column)
        throws SQLException {
        // postgres does not perform automatic conversions, so attempting to
        // get a whole number out of a decimal will throw an exception.
        // fall back to performing manual conversion if the initial get fails
        try {
            return super.getLong(rs, column);
        } catch (SQLException sqle) {
            return super.getBigDecimal(rs, column).longValue();
        }
    }

    /**
     * Handle XML and bytea/oid columns in a PostgreSQL way.
     */
    @Override
    public void setNull(PreparedStatement stmnt, int idx, int colType,
        Column col)
        throws SQLException {
        if (col != null && col.isXML()) {
            stmnt.setNull(idx, Types.OTHER);
            return;
        }

        // OPENJPA-308
        if (colType == Types.BLOB)
            colType = Types.BINARY;
        stmnt.setNull(idx, colType);
    }

    @Override
    protected void appendSelectRange(SQLBuffer buf, long start, long end,
        boolean subselect) {
        if (end != Long.MAX_VALUE)
            buf.append(" LIMIT ").appendValue(end - start);
        if (start != 0)
            buf.append(" OFFSET ").appendValue(start);
    }

    @Override
    public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
        FilterValue start) {
        buf.append("(POSITION(");
        find.appendTo(buf);
        buf.append(" IN ");
        if (start != null)
            substring(buf, str, start, null);
        else
            str.appendTo(buf);
        buf.append(")");
        if (start != null) {
            buf.append(" - 1 + ");
            start.appendTo(buf);
        }
        buf.append(")");
    }

    @Override
    protected boolean supportsDeferredUniqueConstraints() {
        // Postgres only supports deferred foreign key constraints.
        return false;
    }

    @Override
    protected String getSequencesSQL(String schemaName, String sequenceName) {
        return getSequencesSQL(DBIdentifier.newSchema(schemaName), DBIdentifier.newSequence(sequenceName));
    }

    @Override
    protected String getSequencesSQL(DBIdentifier schemaName, DBIdentifier sequenceName) {
        if (DBIdentifier.isNull(schemaName) && DBIdentifier.isNull(sequenceName))
            return allSequencesSQL;
        else if (DBIdentifier.isNull(schemaName))
            return namedSequencesFromAllSchemasSQL;
        else if (DBIdentifier.isNull(sequenceName))
            return allSequencesFromOneSchemaSQL;
        else
            return namedSequenceFromOneSchemaSQL;
    }

    @Override
    public boolean isSystemSequence(String name, String schema,
        boolean targetSchema) {
        return isSystemSequence(DBIdentifier.newTable(name), DBIdentifier.newSchema(schema), targetSchema);
    }

    @Override
    public boolean isSystemSequence(DBIdentifier name, DBIdentifier schema,
        boolean targetSchema) {
        return isSystemSequence(name, schema, targetSchema, null);
    }

    @Override
    public boolean isSystemSequence(DBIdentifier name, DBIdentifier schema,
        boolean targetSchema, Connection conn) {
        if (super.isSystemSequence(name, schema, targetSchema))
            return true;

        if (isOwnedSequence(name, schema, conn)) {
            return true;
        }
        return false;
    }

    /**
     * Uses the native Postgres function pg_get_serial_sequence to determine whether
     * a sequence is owned by the database.  Column types such as bigserial use a
     * system assigned sequence generator of the format: table_column_seq
     *
     * @link http://www.postgresql.org/docs/current/static/functions-info.html
     */
    public boolean isOwnedSequence(DBIdentifier name, DBIdentifier schema, Connection conn) {

        String strName = DBIdentifier.isNull(name) ? "" : name.getName();
        // basic check for SEQ suffix.  not SEQ, not an owned sequence
        if (strName == null || !strName.toUpperCase(Locale.ENGLISH).endsWith("_SEQ"))
            return false;

        // If no connection, use secondary method to determine ownership
        if (conn == null) {
            return isOwnedSequence(strName);
        }

        // Build permutations of table, column pairs from the provided
        // sequence name.  If any of them are determined owned, assume the
        // sequence is owned.  This is not perfect, but considerably better than
        // considering all sequences suffixed with _seq are db owned.
        String[][] namePairs = buildNames(strName);

        if(namePairs != null) { // unable to parse strName.
            try {
                for (String[] namePair : namePairs) {
                    if (queryOwnership(conn, namePair, schema)) {
                        return true;
                    }
                }
            } catch (Throwable t) {
                if (log.isWarnEnabled()) {
                    log.warn(_loc.get("psql-owned-seq-warning"), t);
                }
                return isOwnedSequence(strName);
            }
        } else {
            if(log.isTraceEnabled()) {
                log.trace(String.format("Unable to query ownership for sequence %s using the connection. " +
                                "Falling back to simpler detection based on the name",
                    name.getName()));
            }

            return isOwnedSequence(strName);
        }
        return false;
    }

    private boolean queryOwnership(Connection conn, String[] namePair,
        DBIdentifier schema) throws Throwable {
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = prepareStatement(conn, isOwnedSequenceSQL);
            String tblName = "";
            if (!DBIdentifier.isEmpty(schema)) {
                tblName = schema.getName() + getIdentifierDelimiter();
            }
            tblName += namePair[0];
            ps.setString(1, tblName);
            String colName = toDBName(DBIdentifier.newColumn(namePair[1]));
            ps.setString(2, colName);
            ps.execute();
            rs = ps.getResultSet();
            if (rs == null || !rs.next()) {
                return false;
            }
            String val = getString(rs, 1);
            if (val == null || val.length() == 0) {
                return false;
            }
            return true;
        } catch (Throwable t) {
            if (t instanceof ReportingSQLException) {
                // Handle known/acceptable exceptions
                // 42P01 - table does not exist
                // 42703 - column does not exist within table
                ReportingSQLException rse = (ReportingSQLException)t;
                if ("42P01".equals(rse.getSQLState()) ||
                    "42703".equals(rse.getSQLState())) {
                    return false;
                }
            }
            throw t;
        }
        finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (Throwable t) {}
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (Throwable t) {}
            }
        }
    }

    /**
     * Owned sequences are of the form <table>_<col>_seq. Table and column
     * names can contain underscores so permutations of these names must be
     * produced for ownership verification.
     * @param strName
     * @return If strName cannot be split into three or more parts null will be returned.
     *  Otherwise a String[][] of the potential sequence names will be returned.
     */
    private String[][] buildNames(String strName) {
        // split the sequence name into components
        // owned sequences are of the form <table>_<col>_seq
        String[] parts = Normalizer.splitName(strName, "_");

        if (parts == null || parts.length < 3) {
            if(log.isTraceEnabled()) {
                log.trace(String.format("Unable to parse sequences from %s. Found %s parts. Returning null",
                    strName, parts == null ? 0 : parts.length));
            }
            return null;
        }
        // Simple and most common case
        if (parts.length == 3) {
            return new String[][] { {parts[0], parts[1]} };
        }
        // If table or column names contain underscores, build a list
        // of possibilities
        String[][] names = new String[(parts.length - 2)][2];
        for (int i = 0; i < parts.length - 2; i++) {
            String[] namePair = new String[2];
            StringBuilder name0 = new StringBuilder();
            StringBuilder name1 = new StringBuilder();
            for (int j = 0; j < parts.length - 1; j++) {
                if (j <= i) {
                    name0.append(parts[j]);
                    if (j < i) {
                        name0.append("_");
                    }
                } else {
                    name1.append(parts[j]);
                    if (j < parts.length - 2) {
                        name1.append("_");
                    }
                }
            }
            namePair[0] = name0.toString();
            namePair[1] = name1.toString();
            names[i] = namePair;
        }
        return names;
    }

    /**
     * Secondary logic if owned sequences cannot be determined by calling the
     * db.  This logic assumes that any sequence suffixed with _SEQ is an
     * owned sequence (identical to the behavior of prior versions of OpenJPA).
     * @param strName
     */
    private boolean isOwnedSequence(String strName) {
        // filter out generated sequences used for bigserial cols, which are
        // of the form <table>_<col>_seq
        int idx = (strName == null) ? -1 : strName.indexOf('_');
        return idx != -1 && idx != strName.length() - 4
            && strName.toUpperCase(Locale.ENGLISH).endsWith("_SEQ");
    }

    @Override
    public boolean isSystemTable(String name, String schema,
        boolean targetSchema) {
        return isSystemTable(DBIdentifier.newTable(name), DBIdentifier.newSchema(schema), targetSchema);
    }

    @Override
    public boolean isSystemTable(DBIdentifier name, DBIdentifier schema,
        boolean targetSchema) {
        // names starting with "pg_" are reserved for Postgresql internal use
        String strName = DBIdentifier.isNull(name) ? null : name.getName();
        return super.isSystemTable(name, schema, targetSchema)
            || (strName != null && strName.toLowerCase(Locale.ENGLISH).startsWith("pg_"));
    }

    @Override
    public boolean isSystemIndex(String name, Table table) {
        return isSystemIndex(DBIdentifier.newIndex(name), table);
    }

    @Override
    public boolean isSystemIndex(DBIdentifier name, Table table) {
        // names starting with "pg_" are reserved for Postgresql internal use
        String strName = DBIdentifier.isNull(name) ? null : name.getName();
        return super.isSystemIndex(name, table)
            || (strName != null && strName.toLowerCase(Locale.ENGLISH).startsWith("pg_"));
    }

    @Override
    public Connection decorate(Connection conn)
        throws SQLException {
        return new PostgresConnection(super.decorate(conn), this);
    }

    @Override
    public InputStream getLOBStream(JDBCStore store, ResultSet rs,
        int column) throws SQLException {
        DelegatingConnection conn = (DelegatingConnection)store
            .getConnection();
        conn.setAutoCommit(false);
        LargeObjectManager lom = getLargeObjectManager(conn);
        if (rs.getInt(column) != -1) {
            LargeObject lo = lom.open(rs.getInt(column));
            return lo.getInputStream();
        } else {
            return null;
        }
    }

    @Override
    public void insertBlobForStreamingLoad(Row row, Column col,
        JDBCStore store, Object ob, Select sel) throws SQLException {
        if (row.getAction() == Row.ACTION_INSERT) {
            insertPostgresBlob(row, col, store, ob);
        } else if (row.getAction() == Row.ACTION_UPDATE) {
            updatePostgresBlob(row, col, store, ob, sel);
        }
    }

    private void insertPostgresBlob(Row row, Column col, JDBCStore store,
        Object ob) throws SQLException {
        if (ob != null) {
            col.setType(Types.INTEGER);
            DelegatingConnection conn = (DelegatingConnection)store
            .getConnection();
            try {
                conn.setAutoCommit(false);
                LargeObjectManager lom = getLargeObjectManager(conn);
                // The create method is valid in versions previous to 8.3
                // in 8.3 this method is deprecated, use createLO
                int oid = lom.create();
                LargeObject lo = lom.open(oid, LargeObjectManager.WRITE);
                OutputStream os = lo.getOutputStream();
                copy((InputStream)ob, os);
                lo.close();
                row.setInt(col, oid);
            } catch (IOException ioe) {
                throw new StoreException(ioe);
            } finally {
                conn.close();
            }
        } else {
            row.setInt(col, -1);
        }
    }

    private void updatePostgresBlob(Row row, Column col, JDBCStore store,
        Object ob, Select sel) throws SQLException {
        JDBCFetchConfiguration fetch = store.getFetchConfiguration();
        SQLBuffer sql = sel.toSelect(true, fetch);
        ResultSet res = null;
        DelegatingConnection conn =
            (DelegatingConnection) store.getConnection();
        PreparedStatement stmnt = null;
        try {
            stmnt = sql.prepareStatement(conn, fetch,
                ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            setTimeouts(stmnt, fetch, true);
            res = stmnt.executeQuery();
            if (!res.next()) {
                throw new InternalException(_loc.get("stream-exception"));
            }
            int oid = res.getInt(1);
            if (oid != -1) {
                conn.setAutoCommit(false);
                LargeObjectManager lom = getLargeObjectManager(conn);
                if (ob != null) {
                    LargeObject lo = lom.open(oid, LargeObjectManager.WRITE);
                    OutputStream os = lo.getOutputStream();
                    long size = copy((InputStream) ob, os);
                    lo.truncate((int) size);
                    lo.close();
                } else {
                    lom.delete(oid);
                    row.setInt(col, -1);
                }
            } else {
                if (ob != null) {
                    conn.setAutoCommit(false);
                    LargeObjectManager lom = getLargeObjectManager(conn);
                    oid = lom.create();
                    LargeObject lo = lom.open(oid, LargeObjectManager.WRITE);
                    OutputStream os = lo.getOutputStream();
                    copy((InputStream)ob, os);
                    lo.close();
                    row.setInt(col, oid);
                }
            }

        } catch (IOException ioe) {
            throw new StoreException(ioe);
        } finally {
            if (res != null)
                try { res.close (); } catch (SQLException e) {}
            if (stmnt != null)
                try { stmnt.close (); } catch (SQLException e) {}
            if (conn != null)
                try { conn.close (); } catch (SQLException e) {}
        }

    }

    @Override
    public void updateBlob(Select sel, JDBCStore store, InputStream is)
        throws SQLException {
        //Do nothing
    }

    @Override
    public void deleteStream(JDBCStore store, Select sel) throws SQLException {
        JDBCFetchConfiguration fetch = store.getFetchConfiguration();
        SQLBuffer sql = sel.toSelect(true, fetch);
        ResultSet res = null;
        DelegatingConnection conn =
            (DelegatingConnection) store.getConnection();
        PreparedStatement stmnt = null;
        try {
            stmnt = sql.prepareStatement(conn, fetch,
                ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            setTimeouts(stmnt, fetch, true);
            res = stmnt.executeQuery();
            if (!res.next()) {
                throw new InternalException(_loc.get("stream-exception"));
            }
            int oid = res.getInt(1);
            if (oid != -1) {
                conn.setAutoCommit(false);
                LargeObjectManager lom = getLargeObjectManager(conn);
                lom.delete(oid);
            }
        } finally {
            if (res != null)
                try { res.close (); } catch (SQLException e) {}
            if (stmnt != null)
                try { stmnt.close (); } catch (SQLException e) {}
            if (conn != null)
                try { conn.close (); } catch (SQLException e) {}
        }
    }


    @Override
    public LocalDate getLocalDate(ResultSet rs, int column) throws SQLException {
        return rs.getObject(column, LocalDate.class);
    }

    @Override
    public LocalTime getLocalTime(ResultSet rs, int column) throws SQLException {
        return rs.getObject(column, LocalTime.class);
    }

    @Override
    public LocalDateTime getLocalDateTime(ResultSet rs, int column) throws SQLException {
        return rs.getObject(column, LocalDateTime.class);
    }

    @Override
    public OffsetDateTime getOffsetDateTime(ResultSet rs, int column) throws SQLException {
        return rs.getObject(column, OffsetDateTime.class);
    }

    /**
     * default column type for OffsetTime is 'time with time zone'.
     * But opposed to the name PostgreSQL internally stores those values in UTC time
     * without any timezone.
     */
    @Override
    public void setOffsetTime(PreparedStatement stmnt, int idx, OffsetTime val, Column col) throws SQLException {
        // this is really a whacky hack somehow
        // PostgreSQL doesn't support OffsetTime natively.
        // The JDBC driver will automatically convert this to UTC which is the
        // internal normalised TimeZone PostgreSQL uses.
        LocalTime utcTime = val.withOffsetSameInstant(OffsetDateTime.now().getOffset()).toLocalTime();
        stmnt.setTime(idx, java.sql.Time.valueOf(utcTime));
    }

    @Override
    public OffsetTime getOffsetTime(ResultSet rs, int column) throws SQLException {
        final java.sql.Time utcTime = rs.getTime(column);
        if (utcTime != null) {
            return utcTime.toLocalTime().atOffset(OffsetDateTime.now().getOffset());
        }
        return null;
    }

    @Override
    public void setLocalDate(PreparedStatement stmnt, int idx, LocalDate val, Column col) throws SQLException {
        stmnt.setObject(idx, val);
    }

    @Override
    public void setLocalTime(PreparedStatement stmnt, int idx, LocalTime val, Column col) throws SQLException {
        stmnt.setObject(idx, val);
    }

    @Override
    public void setLocalDateTime(PreparedStatement stmnt, int idx, LocalDateTime val, Column col) throws SQLException {
        stmnt.setObject(idx, val);
    }

    @Override
    public void setOffsetDateTime(PreparedStatement stmnt, int idx, OffsetDateTime val, Column col) throws SQLException {
        stmnt.setObject(idx, val);
    }

    /**
     * Determine XML column support and backslash handling, etc
     */
    @Override
    public void connectedConfiguration(Connection conn) throws SQLException {
        super.connectedConfiguration(conn);

        DatabaseMetaData metaData = conn.getMetaData();
        int maj = 0;
        int min = 0;
        if (isJDBC3) {
            maj = metaData.getDatabaseMajorVersion();
            min = metaData.getDatabaseMinorVersion();
        } else {
            try {
                // The product version looks like "8.3.5".
                String productVersion = metaData.getDatabaseProductVersion();
                String majMin[] = productVersion.split("\\.");
                maj = Integer.parseInt(majMin[0]);
                min = Integer.parseInt(majMin[1]);
            } catch (Exception e) {
                // We don't understand the version format.
                if (log.isWarnEnabled())
                    log.warn(e.toString(),e);
            }
        }

        if ((maj >= 9 || (maj == 8 && min >= 3))) {
            supportsXMLColumn = true;
        }
        if (maj < 10) {
            // setQueryTimeout only got implemented pretty late
            supportsQueryTimeout = false;
        }

        // Old PostgreSQL requires double-escape for strings.
        if ((maj <= 8 || (maj == 9 && min == 0))) {
            searchStringEscape = "\\\\";
        }
    }

    @Override
    public boolean isFatalException(int subtype, SQLException ex) {
        if ((subtype == StoreException.LOCK  && "57014".equals(ex.getSQLState()))) {
            return false;
        }
        return super.isFatalException(subtype, ex);
    }

    /**
     * If column is an XML column, PostgreSQL requires that its value is set
     * by using {@link PreparedStatement#setObject(int, Object, int)}
     * with {@link Types#OTHER} as the third argument.
     */
    @Override
    public void setClobString(PreparedStatement stmnt, int idx, String val,
        Column col) throws SQLException {
        if (col != null && col.isXML())
            stmnt.setObject(idx, val, Types.OTHER);
        else
            super.setClobString(stmnt, idx, val, col);
    }

    /**
     * Override the getOjbect() method to handle the case where the latest
     * Postgres JDBC driver returns a org.postgresql.util.PGobject instead of a
     * java.sql.Timestamp
     *
     * @param rs
     * @param column
     * @param map
     *
     * @exception SQLException
     */
    @Override
    public Object getObject(ResultSet rs, int column, Map map)
        throws SQLException {
        Object obj = super.getObject(rs, column, map);

        if (obj == null) {
            return null;
        }
        if (obj.getClass().getName().equals("org.postgresql.util.PGobject")) {
            try {
                Method m = obj.getClass().getMethod("getType", (Class[]) null);
                Object type = m.invoke(obj, (Object[]) null);
                if(_timestampTypes.contains(((String) type).toUpperCase(Locale.ENGLISH))) {
                    return rs.getTimestamp(column);
                }
            } catch (Throwable t) {
                if (t instanceof InvocationTargetException)
                    t = ((InvocationTargetException) t).getTargetException();
                if (t instanceof SQLException)
                    throw (SQLException) t;
                throw new SQLException(t.getMessage());
            }
        }
        return obj;
    }

    /**
     * Append XML comparison.
     *
     * @param buf
     *            the SQL buffer to write the comparison
     * @param op
     *            the comparison operation to perform
     * @param lhs
     *            the left hand side of the comparison
     * @param rhs
     *            the right hand side of the comparison
     * @param lhsxml
     *            indicates whether the left operand maps to XML
     * @param rhsxml
     *            indicates whether the right operand maps to XML
     */
    @Override
    public void appendXmlComparison(SQLBuffer buf, String op, FilterValue lhs,
        FilterValue rhs, boolean lhsxml, boolean rhsxml) {
        super.appendXmlComparison(buf, op, lhs, rhs, lhsxml, rhsxml);
        if (lhsxml)
            appendXmlValue(buf, lhs);
        else
            lhs.appendTo(buf);
        buf.append(" ").append(op).append(" ");
        if (rhsxml)
            appendXmlValue(buf, rhs);
        else
            rhs.appendTo(buf);
    }

    /**
     * Append XML column value so that it can be used in comparisons.
     *
     * @param buf
     *            the SQL buffer to write the value
     * @param val
     *            the value to be written
     */
    private void appendXmlValue(SQLBuffer buf, FilterValue val) {
        Class rc = Filters.wrap(val.getType());
        int type = getJDBCType(JavaTypes.getTypeCode(rc), false);
        boolean isXmlAttribute = (val.getXmlMapping() == null) ? false
                : val.getXmlMapping().isXmlAttribute();
        SQLBuffer newBufer = new SQLBuffer(this);
        newBufer.append("(xpath('/*/");
        val.appendTo(newBufer);
        if (!isXmlAttribute)
            newBufer.append("/text()");
        newBufer.append("',").
            append(val.getColumnAlias(val.getFieldMapping().getColumns()[0])).
            append("))[1]");
        appendCast(buf, newBufer, type);
    }


    /**
     * Return a SQL string to act as a placeholder for the given column.
     */
    @Override
    public String getPlaceholderValueString(Column col) {
        if (col.getType() == Types.BIT) {
            return "false";
        } else {
            return super.getPlaceholderValueString(col);
        }
    }

    /**
     * Get the native PostgreSQL Large Object Manager used for LOB handling.
     */
    protected LargeObjectManager getLargeObjectManager(DelegatingConnection conn) throws SQLException {
        return getPGConnection(conn).getLargeObjectAPI();
    }

    /**
     * Get the native PostgreSQL connection from the given connection.
     * Various attempts of unwrapping are being performed.
     */
    protected PGConnection getPGConnection(DelegatingConnection conn) {
        Connection innerConn = conn.getInnermostDelegate();
        if (innerConn instanceof PGConnection) {
            return (PGConnection) innerConn;
        }
        if (innerConn.getClass().getName().startsWith("org.apache.commons.dbcp2")) {
            return (PGConnection) getDbcpDelegate(innerConn);
        }
        return (PGConnection) unwrapConnection(conn, PGConnection.class);
    }

    /**
     * Get the delegated connection from the given DBCP connection.
     *
     * @param conn must be a DBCP connection
     * @return connection the DBCP connection delegates to
     */
    protected Connection getDbcpDelegate(Connection conn) {
        Connection delegate = null;
        try {
            if (dbcpGetDelegate == null) {
                Class<?> dbcpConnectionClass =
                    Class.forName("org.apache.commons.dbcp2.DelegatingConnection", true, AccessController
                        .doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()));
                Class<?> poolingDataSource = Class.forName(
                        "org.apache.commons.dbcp2.PoolingDataSource", true,
                        AccessController.doPrivileged(J2DoPrivHelper
                                .getContextClassLoaderAction()));
                Method setAccessToUnderlyingConnectionAllowed = poolingDataSource
                        .getMethod("setAccessToUnderlyingConnectionAllowed",
                                boolean.class);

                Field this$0 = conn.getClass().getDeclaredField("this$0");
                this$0.setAccessible(true);
                Object poolingDataSourceObj = this$0.get(conn);
                setAccessToUnderlyingConnectionAllowed.invoke(poolingDataSourceObj,
                        true);

                dbcpGetDelegate = dbcpConnectionClass.getMethod("getInnermostDelegate");
            }
            delegate = (Connection) dbcpGetDelegate.invoke(conn);
        } catch (Exception e) {
            throw new InternalException(_loc.get("dbcp-unwrap-failed"), e);
        }
        if (delegate == null) {
            throw new InternalException(_loc.get("dbcp-unwrap-failed"));
        }
        return delegate;
    }

    /**
     * Get (unwrap) the delegated connection from the given connection.
     * Use reflection to attempt to unwrap a connection.
     * Note: This is a JDBC 4 operation, so it requires a Java 6 environment
     * with a JDBC 4 driver or data source to have any chance of success.
     *
     * @param conn a delegating connection
     * @param connectionClass the expected type of delegated connection
     * @return connection the given connection delegates to
     */
    private Connection unwrapConnection(Connection conn, Class<?> connectionClass) {
        try {
            if (connectionUnwrap == null) {
                connectionUnwrap = Connection.class.getMethod("unwrap", Class.class);
            }
            return (Connection) connectionUnwrap.invoke(conn, connectionClass);
        } catch (Exception e) {
            throw new InternalException(_loc.get("connection-unwrap-failed"), e);
        }
    }

    /**
     * Connection wrapper to work around the postgres empty result set bug.
     */
    protected static class PostgresConnection extends DelegatingConnection {

        private final PostgresDictionary _dict;

        public PostgresConnection(Connection conn, PostgresDictionary dict) {
            super(conn);
            _dict = dict;
        }

        @Override
        protected PreparedStatement prepareStatement(String sql, boolean wrap)
            throws SQLException {
           return new PostgresPreparedStatement(super.prepareStatement(sql, false), PostgresConnection.this, _dict);
        }

        @Override
        protected PreparedStatement prepareStatement(String sql, int rsType,
            int rsConcur, boolean wrap)
            throws SQLException {
            return new PostgresPreparedStatement(super.prepareStatement(sql, rsType, rsConcur, false),
                    PostgresConnection.this,
                    _dict);
        }
    }

    /**
     * Statement wrapper to work around the postgres empty result set bug.
     */
    protected static class PostgresPreparedStatement extends DelegatingPreparedStatement {

        private final PostgresDictionary _dict;

        public PostgresPreparedStatement(PreparedStatement ps,
            Connection conn, PostgresDictionary dict) {
            super(ps, conn);
            _dict = dict;
        }

        @Override
        protected ResultSet executeQuery(boolean wrap)
            throws SQLException {
            try {
                return super.executeQuery(wrap);
            } catch (SQLException se) {
                // we need to make our best guess whether this is the empty
                // ResultSet bug, since this exception could occur
                // for other reasons (like an invalid query string). Note
                // that Postgres error messages are localized, so we
                // cannot just parse the exception String.
                ResultSet rs = getResultSet(wrap);

                // ResultSet should be empty: if not, then maybe an
                // actual error occurred
                if (rs == null)
                    throw se;

                return rs;
            }
        }

        @Override
        public void setFetchSize(int i)
            throws SQLException {
            // some postgres drivers do not support the setFetchSize method
            try {
                if (_dict.supportsSetFetchSize)
                    super.setFetchSize(i);
            } catch (SQLException e) {
                _dict.supportsSetFetchSize = false;
                if (_dict.log.isWarnEnabled())
                    _dict.log.warn(_loc.get("psql-no-set-fetch-size"), e);
            }
        }
    }
}

