<commit_before>/*
 * DBeaver - Universal Database Manager
 * Copyright (C) 2010-2017 <NAME> (<EMAIL>)
 *
 * Licensed 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.jkiss.dbeaver.model.impl.jdbc;

import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataTypeProvider;
import org.jkiss.dbeaver.model.edit.DBEPersistAction;
import org.jkiss.dbeaver.model.edit.DBERegistry;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCTable;
import org.jkiss.dbeaver.model.impl.sql.edit.SQLObjectEditor;
import org.jkiss.dbeaver.model.impl.sql.edit.struct.SQLTableManager;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.struct.DBSObjectFilter;
import org.jkiss.dbeaver.model.struct.rdb.DBSForeignKeyModifyRule;
import org.jkiss.utils.CommonUtils;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.*;
import java.util.List;

/**
 * JDBCUtils
 */
public class JDBCUtils {
    private static final Log log = Log.getLog(JDBCUtils.class);
    public static final int CONNECTION_VALIDATION_TIMEOUT = 5000;

    @Nullable
    public static String safeGetString(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getString(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetStringTrimmed(ResultSet dbResult, String columnName)
    {
        try {
            final String value = dbResult.getString(columnName);
            if (value != null && !value.isEmpty()) {
                return value.trim();
            } else {
                return value;
            }
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetString(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getString(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetStringTrimmed(ResultSet dbResult, int columnIndex)
    {
        try {
            final String value = dbResult.getString(columnIndex);
            if (value != null && !value.isEmpty()) {
                return value.trim();
            } else {
                return value;
            }
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    public static int safeGetInt(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getInt(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return 0;
        }
    }

    public static int safeGetInt(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getInt(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static Integer safeGetInteger(ResultSet dbResult, String columnName)
    {
        try {
            final int result = dbResult.getInt(columnName);
            if (dbResult.wasNull()) {
                return null;
            } else {
                return result;
            }
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Integer safeGetInteger(ResultSet dbResult, int columnIndex)
    {
        try {
            final int result = dbResult.getInt(columnIndex);
            if (dbResult.wasNull()) {
                return null;
            } else {
                return result;
            }
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    public static long safeGetLong(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getLong(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return 0;
        }
    }

    public static long safeGetLong(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getLong(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static Long safeGetLongNullable(ResultSet dbResult, String columnName)
    {
        try {
            final long result = dbResult.getLong(columnName);
            return dbResult.wasNull() ? null : result;
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    public static double safeGetDouble(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getDouble(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return 0.0;
        }
    }

    public static double safeGetDouble(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getDouble(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return 0.0;
        }
    }

    public static float safeGetFloat(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getFloat(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return 0;
        }
    }

    public static float safeGetFloat(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getFloat(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static BigDecimal safeGetBigDecimal(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBigDecimal(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static BigDecimal safeGetBigDecimal(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getBigDecimal(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBoolean(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return false;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getBoolean(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return false;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, String columnName, String trueValue)
    {
        try {
            final String strValue = dbResult.getString(columnName);
            return strValue != null && strValue.startsWith(trueValue);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return false;
        }
    }

    @Nullable
    public static byte[] safeGetBytes(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBytes(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Timestamp safeGetTimestamp(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getTimestamp(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Timestamp safeGetTimestamp(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getTimestamp(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Date safeGetDate(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getDate(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Date safeGetDate(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getDate(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Time safeGetTime(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getTime(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Time safeGetTime(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getTime(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static SQLXML safeGetXML(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getSQLXML(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static SQLXML safeGetXML(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getSQLXML(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetObject(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getObject(columnName);
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetObject(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getObject(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static <T> T safeGetArray(ResultSet dbResult, String columnName)
    {
        try {
            Array array = dbResult.getArray(columnName);
            return array == null ? null : (T) array.getArray();
        } catch (SQLException e) {
            debugColumnRead(columnName, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetArray(ResultSet dbResult, int columnIndex)
    {
        try {
            Array array = dbResult.getArray(columnIndex);
            return array == null ? null : array.getArray();
        } catch (SQLException e) {
            debugColumnRead(columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static String normalizeIdentifier(@Nullable String value)
    {
        return value == null ? null : value.trim();
    }

    public static void dumpResultSet(ResultSet dbResult)
    {
        try {
            ResultSetMetaData md = dbResult.getMetaData();
            int count = md.getColumnCount();
            dumpResultSetMetaData(dbResult);
            while (dbResult.next()) {
                for (int i = 1; i <= count; i++) {
                    String colValue = dbResult.getString(i);
                    System.out.print(colValue + "\t");
                }
                System.out.println();
            }
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void dumpResultSetMetaData(ResultSet dbResult)
    {
        try {
            ResultSetMetaData md = dbResult.getMetaData();
            int count = md.getColumnCount();
            for (int i = 1; i <= count; i++) {
                System.out.print(md.getColumnName(i) + " [" + md.getColumnTypeName(i) + "]\t");
            }
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static boolean isConnectionAlive(DBPDataSource dataSource, Connection connection)
    {
        try {
            if (connection.isClosed()) {
                return false;
            }
        } catch (SQLException e) {
            log.debug(e);
            return false;
        }
        String testSQL = null;
        if (dataSource instanceof SQLDataSource) {
            testSQL = ((SQLDataSource) dataSource).getSQLDialect().getTestSQL();
        }
        try {
            if (!CommonUtils.isEmpty(testSQL)) {
                // Execute test SQL
                try (Statement dbStat = connection.createStatement()) {
                    dbStat.execute(testSQL);
                }
            } else {
                try {
                    return connection.isValid(CONNECTION_VALIDATION_TIMEOUT);
                } catch (Throwable e) {
                    // isValid may be unsupported by driver
                    // Let's try to read table list
                    connection.getMetaData().getTables(null, null, "DBEAVER_FAKE_TABLE_NAME_FOR_PING", null);
                }
            }
            return true;
        } catch (Throwable e1) {
            log.debug("Connection seems to be broken", e1);
            return false;
        }
    }

    public static void scrollResultSet(ResultSet dbResult, long offset, boolean forceFetch) throws SQLException
    {
        // Scroll to first row
        boolean scrolled = false;
        if (!forceFetch) {
            try {
                scrolled = dbResult.absolute((int) offset);
            } catch (SQLException | UnsupportedOperationException | IncompatibleClassChangeError e) {
                // Seems to be not supported
                log.debug(e.getMessage());
            }
        }
        if (!scrolled) {
            // Just fetch first 'firstRow' rows
            for (long i = 1; i <= offset; i++) {
                try {
                    dbResult.next();
                } catch (SQLException e) {
                    throw new SQLException("Can't scroll result set to row " + offset, e);
                }
            }
        }
    }

    public static void reportWarnings(JDBCSession session, SQLWarning rootWarning)
    {
        for (SQLWarning warning = rootWarning; warning != null; warning = warning.getNextWarning()) {
            if (warning.getMessage() == null && warning.getErrorCode() == 0) {
                // Skip trash [Excel driver]
                continue;
            }
            log.warn("SQL Warning (DataSource: " + session.getDataSource().getContainer().getName() + "; Code: "
                + warning.getErrorCode() + "; State: " + warning.getSQLState() + "): " + warning.getLocalizedMessage());
        }
    }

    @NotNull
    public static String limitQueryLength(@NotNull String query, int maxLength)
    {
        return query.length() <= maxLength ? query : query.substring(0, maxLength);
    }

    public static DBSForeignKeyModifyRule getCascadeFromNum(int num)
    {
        switch (num) {
        case DatabaseMetaData.importedKeyNoAction:
            return DBSForeignKeyModifyRule.NO_ACTION;
        case DatabaseMetaData.importedKeyCascade:
            return DBSForeignKeyModifyRule.CASCADE;
        case DatabaseMetaData.importedKeySetNull:
            return DBSForeignKeyModifyRule.SET_NULL;
        case DatabaseMetaData.importedKeySetDefault:
            return DBSForeignKeyModifyRule.SET_DEFAULT;
        case DatabaseMetaData.importedKeyRestrict:
            return DBSForeignKeyModifyRule.RESTRICT;
        default:
            return DBSForeignKeyModifyRule.UNKNOWN;
        }
    }

    public static void executeSQL(Connection session, String sql, Object ... params) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareStatement(sql)) {
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    dbStat.setObject(i + 1, params[i]);
                }
            }
            dbStat.execute();
        }
    }

    public static void executeProcedure(Connection session, String sql) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareCall(sql)) {
            dbStat.execute();
        }
    }

    public static <T> T executeQuery(Connection session, String sql, Object ... params) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareStatement(sql)) {
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    dbStat.setObject(i + 1, params[i]);
                }
            }
            try (ResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return (T) resultSet.getObject(1);
                } else {
                    return null;
                }
            }
        }
    }

    @Nullable
    public static String queryString(JDBCSession session, String sql, Object... args) throws SQLException
    {
        try (JDBCPreparedStatement dbStat = session.prepareStatement(sql)) {
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    dbStat.setObject(i + 1, args[i]);
                }
            }
            try (JDBCResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return resultSet.getString(1);
                } else {
                    return null;
                }
            }
        }
    }

    @Nullable
    public static <T> T queryObject(JDBCSession session, String sql, Object... args) throws SQLException
    {
        try (JDBCPreparedStatement dbStat = session.prepareStatement(sql)) {
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    dbStat.setObject(i + 1, args[i]);
                }
            }
            try (JDBCResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return (T) resultSet.getObject(1);
                } else {
                    return null;
                }
            }
        }
    }

    private static void debugColumnRead(String columnName, SQLException error)
    {
        log.debug("Can't get column '" + columnName + "': " + error.getMessage());
    }

    private static void debugColumnRead(int columnIndex, SQLException error)
    {
        log.debug("Can't get column #" + columnIndex + ": " + error.getMessage());
    }

    public static void appendFilterClause(StringBuilder sql, DBSObjectFilter filter, String columnAlias, boolean firstClause)
    {
        if (filter.isNotApplicable()) {
            return;
        }
        if (filter.hasSingleMask()) {
            firstClause = SQLUtils.appendFirstClause(sql, firstClause);
            sql.append(columnAlias);
            SQLUtils.appendLikeCondition(sql, filter.getSingleMask(), false);
            return;
        }
        List<String> include = filter.getInclude();
        if (!CommonUtils.isEmpty(include)) {
            firstClause = SQLUtils.appendFirstClause(sql, firstClause);
            sql.append("(");
            for (int i = 0, includeSize = include.size(); i < includeSize; i++) {
                if (i > 0)
                    sql.append(" OR ");
                sql.append(columnAlias);
                SQLUtils.appendLikeCondition(sql, include.get(i), false);
            }
            sql.append(")");
        }
        List<String> exclude = filter.getExclude();
        if (!CommonUtils.isEmpty(exclude)) {<commit_msg>Generic driver logging fix (remove dups)<commit_after>/*
 * DBeaver - Universal Database Manager
 * Copyright (C) 2010-2017 <NAME> (<EMAIL>)
 *
 * Licensed 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.jkiss.dbeaver.model.impl.jdbc;

import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataKind;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataTypeProvider;
import org.jkiss.dbeaver.model.edit.DBEPersistAction;
import org.jkiss.dbeaver.model.edit.DBERegistry;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession;
import org.jkiss.dbeaver.model.impl.jdbc.struct.JDBCTable;
import org.jkiss.dbeaver.model.impl.sql.edit.SQLObjectEditor;
import org.jkiss.dbeaver.model.impl.sql.edit.struct.SQLTableManager;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.struct.DBSObjectFilter;
import org.jkiss.dbeaver.model.struct.rdb.DBSForeignKeyModifyRule;
import org.jkiss.utils.CommonUtils;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JDBCUtils
 */
public class JDBCUtils {
    private static final Log log = Log.getLog(JDBCUtils.class);
    public static final int CONNECTION_VALIDATION_TIMEOUT = 5000;

    private static final Map<String, Integer> badColumnNames = new HashMap<>();

    @Nullable
    public static String safeGetString(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getString(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetStringTrimmed(ResultSet dbResult, String columnName)
    {
        try {
            final String value = dbResult.getString(columnName);
            if (value != null && !value.isEmpty()) {
                return value.trim();
            } else {
                return value;
            }
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetString(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getString(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static String safeGetStringTrimmed(ResultSet dbResult, int columnIndex)
    {
        try {
            final String value = dbResult.getString(columnIndex);
            if (value != null && !value.isEmpty()) {
                return value.trim();
            } else {
                return value;
            }
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    public static int safeGetInt(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getInt(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return 0;
        }
    }

    public static int safeGetInt(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getInt(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static Integer safeGetInteger(ResultSet dbResult, String columnName)
    {
        try {
            final int result = dbResult.getInt(columnName);
            if (dbResult.wasNull()) {
                return null;
            } else {
                return result;
            }
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Integer safeGetInteger(ResultSet dbResult, int columnIndex)
    {
        try {
            final int result = dbResult.getInt(columnIndex);
            if (dbResult.wasNull()) {
                return null;
            } else {
                return result;
            }
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    public static long safeGetLong(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getLong(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return 0;
        }
    }

    public static long safeGetLong(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getLong(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static Long safeGetLongNullable(ResultSet dbResult, String columnName)
    {
        try {
            final long result = dbResult.getLong(columnName);
            return dbResult.wasNull() ? null : result;
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    public static double safeGetDouble(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getDouble(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return 0.0;
        }
    }

    public static double safeGetDouble(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getDouble(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return 0.0;
        }
    }

    public static float safeGetFloat(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getFloat(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return 0;
        }
    }

    public static float safeGetFloat(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getFloat(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return 0;
        }
    }

    @Nullable
    public static BigDecimal safeGetBigDecimal(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBigDecimal(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static BigDecimal safeGetBigDecimal(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getBigDecimal(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBoolean(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return false;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getBoolean(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return false;
        }
    }

    public static boolean safeGetBoolean(ResultSet dbResult, String columnName, String trueValue)
    {
        try {
            final String strValue = dbResult.getString(columnName);
            return strValue != null && strValue.startsWith(trueValue);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return false;
        }
    }

    @Nullable
    public static byte[] safeGetBytes(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getBytes(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Timestamp safeGetTimestamp(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getTimestamp(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Timestamp safeGetTimestamp(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getTimestamp(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Date safeGetDate(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getDate(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Date safeGetDate(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getDate(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Time safeGetTime(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getTime(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Time safeGetTime(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getTime(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static SQLXML safeGetXML(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getSQLXML(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static SQLXML safeGetXML(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getSQLXML(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetObject(ResultSet dbResult, String columnName)
    {
        try {
            return dbResult.getObject(columnName);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetObject(ResultSet dbResult, int columnIndex)
    {
        try {
            return dbResult.getObject(columnIndex);
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static <T> T safeGetArray(ResultSet dbResult, String columnName)
    {
        try {
            Array array = dbResult.getArray(columnName);
            return array == null ? null : (T) array.getArray();
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnName, e);
            return null;
        }
    }

    @Nullable
    public static Object safeGetArray(ResultSet dbResult, int columnIndex)
    {
        try {
            Array array = dbResult.getArray(columnIndex);
            return array == null ? null : array.getArray();
        } catch (SQLException e) {
            debugColumnRead(dbResult, columnIndex, e);
            return null;
        }
    }

    @Nullable
    public static String normalizeIdentifier(@Nullable String value)
    {
        return value == null ? null : value.trim();
    }

    public static void dumpResultSet(ResultSet dbResult)
    {
        try {
            ResultSetMetaData md = dbResult.getMetaData();
            int count = md.getColumnCount();
            dumpResultSetMetaData(dbResult);
            while (dbResult.next()) {
                for (int i = 1; i <= count; i++) {
                    String colValue = dbResult.getString(i);
                    System.out.print(colValue + "\t");
                }
                System.out.println();
            }
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void dumpResultSetMetaData(ResultSet dbResult)
    {
        try {
            ResultSetMetaData md = dbResult.getMetaData();
            int count = md.getColumnCount();
            for (int i = 1; i <= count; i++) {
                System.out.print(md.getColumnName(i) + " [" + md.getColumnTypeName(i) + "]\t");
            }
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static boolean isConnectionAlive(DBPDataSource dataSource, Connection connection)
    {
        try {
            if (connection.isClosed()) {
                return false;
            }
        } catch (SQLException e) {
            log.debug(e);
            return false;
        }
        String testSQL = null;
        if (dataSource instanceof SQLDataSource) {
            testSQL = ((SQLDataSource) dataSource).getSQLDialect().getTestSQL();
        }
        try {
            if (!CommonUtils.isEmpty(testSQL)) {
                // Execute test SQL
                try (Statement dbStat = connection.createStatement()) {
                    dbStat.execute(testSQL);
                }
            } else {
                try {
                    return connection.isValid(CONNECTION_VALIDATION_TIMEOUT);
                } catch (Throwable e) {
                    // isValid may be unsupported by driver
                    // Let's try to read table list
                    connection.getMetaData().getTables(null, null, "DBEAVER_FAKE_TABLE_NAME_FOR_PING", null);
                }
            }
            return true;
        } catch (Throwable e1) {
            log.debug("Connection seems to be broken", e1);
            return false;
        }
    }

    public static void scrollResultSet(ResultSet dbResult, long offset, boolean forceFetch) throws SQLException
    {
        // Scroll to first row
        boolean scrolled = false;
        if (!forceFetch) {
            try {
                scrolled = dbResult.absolute((int) offset);
            } catch (SQLException | UnsupportedOperationException | IncompatibleClassChangeError e) {
                // Seems to be not supported
                log.debug(e.getMessage());
            }
        }
        if (!scrolled) {
            // Just fetch first 'firstRow' rows
            for (long i = 1; i <= offset; i++) {
                try {
                    dbResult.next();
                } catch (SQLException e) {
                    throw new SQLException("Can't scroll result set to row " + offset, e);
                }
            }
        }
    }

    public static void reportWarnings(JDBCSession session, SQLWarning rootWarning)
    {
        for (SQLWarning warning = rootWarning; warning != null; warning = warning.getNextWarning()) {
            if (warning.getMessage() == null && warning.getErrorCode() == 0) {
                // Skip trash [Excel driver]
                continue;
            }
            log.warn("SQL Warning (DataSource: " + session.getDataSource().getContainer().getName() + "; Code: "
                + warning.getErrorCode() + "; State: " + warning.getSQLState() + "): " + warning.getLocalizedMessage());
        }
    }

    @NotNull
    public static String limitQueryLength(@NotNull String query, int maxLength)
    {
        return query.length() <= maxLength ? query : query.substring(0, maxLength);
    }

    public static DBSForeignKeyModifyRule getCascadeFromNum(int num)
    {
        switch (num) {
        case DatabaseMetaData.importedKeyNoAction:
            return DBSForeignKeyModifyRule.NO_ACTION;
        case DatabaseMetaData.importedKeyCascade:
            return DBSForeignKeyModifyRule.CASCADE;
        case DatabaseMetaData.importedKeySetNull:
            return DBSForeignKeyModifyRule.SET_NULL;
        case DatabaseMetaData.importedKeySetDefault:
            return DBSForeignKeyModifyRule.SET_DEFAULT;
        case DatabaseMetaData.importedKeyRestrict:
            return DBSForeignKeyModifyRule.RESTRICT;
        default:
            return DBSForeignKeyModifyRule.UNKNOWN;
        }
    }

    public static void executeSQL(Connection session, String sql, Object ... params) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareStatement(sql)) {
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    dbStat.setObject(i + 1, params[i]);
                }
            }
            dbStat.execute();
        }
    }

    public static void executeProcedure(Connection session, String sql) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareCall(sql)) {
            dbStat.execute();
        }
    }

    public static <T> T executeQuery(Connection session, String sql, Object ... params) throws SQLException
    {
        try (PreparedStatement dbStat = session.prepareStatement(sql)) {
            if (params != null) {
                for (int i = 0; i < params.length; i++) {
                    dbStat.setObject(i + 1, params[i]);
                }
            }
            try (ResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return (T) resultSet.getObject(1);
                } else {
                    return null;
                }
            }
        }
    }

    @Nullable
    public static String queryString(JDBCSession session, String sql, Object... args) throws SQLException
    {
        try (JDBCPreparedStatement dbStat = session.prepareStatement(sql)) {
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    dbStat.setObject(i + 1, args[i]);
                }
            }
            try (JDBCResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return resultSet.getString(1);
                } else {
                    return null;
                }
            }
        }
    }

    @Nullable
    public static <T> T queryObject(JDBCSession session, String sql, Object... args) throws SQLException
    {
        try (JDBCPreparedStatement dbStat = session.prepareStatement(sql)) {
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    dbStat.setObject(i + 1, args[i]);
                }
            }
            try (JDBCResultSet resultSet = dbStat.executeQuery()) {
                if (resultSet.next()) {
                    return (T) resultSet.getObject(1);
                } else {
                    return null;
                }
            }
        }
    }

    private static void debugColumnRead(ResultSet dbResult, String columnName, SQLException error)
    {
        String colFullId = columnName;
        if (dbResult instanceof JDBCResultSet) {
            colFullId += ":" + ((JDBCResultSet) dbResult).getSession().getDataSource().getContainer().getId();
        }
        synchronized (badColumnNames) {
            final Integer errorCount = badColumnNames.get(colFullId);
            if (errorCount == null) {
                log.debug("Can't get column '" + columnName + "': " + error.getMessage());
            }
            badColumnNames.put(colFullId, errorCount == null ? 0 : errorCount + 1);
        }
    }

    private static void debugColumnRead(ResultSet dbResult, int columnIndex, SQLException error)
    {
        debugColumnRead(dbResult, "#" + columnIndex, error);
    }

    public static void appendFilterClause(StringBuilder sql, DBSObjectFilter filter, String columnAlias, boolean firstClause)
    {
        if (filter.isNotApplicable()) {
            return;
        }
        if (filter.hasSingleMask()) {
            firstClause = SQLUtils.appendFirstClause(sql, firstClause);
            sql.append(columnAlias);
            SQLUtils.appendLikeCondition(sql, filter.getSingleMask(), false);
            return;
        }
        List<String> include = filter.getInclude();
        if (!CommonUtils.isEmpty(include)) {
            firstClause = SQLUtils.appendFirstClause(sql, firstClause);
            sql.append("(");
            for (int i = 0, includeSize = include.size(); i < includeSize; i++) {
                if (i > 0)
                    sql.append(" OR ");
                sql.append(columnAlias);
                SQLUtils.appendLikeCondition(sql, include.get(i), false);
            }
            sql.append(")");
        }
        List<String> exclude = filter.getExclude();
        if (!CommonUtils.isEmpty(exclude)) {
{'fraction_non_alphanumeric': 0.09063682585378312, 'fraction_numerical': 0.0021823416061105567, 'mean_word_length': 1.8379233100540255, 'pattern_counts': {'":': 2, '<': 37, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4744316', 'n_tokens_mistral': 11566, 'n_tokens_neox': 11287, 'n_words': 2765}