class SqlStatementsSource {
    protected final Configuration configuration;

    private static final Logger logger = LoggerFactory.getLogger(SqlStatementsSource.class);

    SqlStatementsSource(Configuration configuration) {
        this.configuration = configuration;
    }

    static SqlStatementsSource create(Configuration configuration) {
        DatabaseProduct databaseProduct = getDatabaseProduct(configuration);

        if (configuration.getUseDbTime()) {
            var statementsSource = databaseProduct.getDbTimeStatementSource(configuration);
            logger.debug("Using {}", statementsSource.getClass().getSimpleName());
            return statementsSource;
        } else {
            if (Objects.equals(databaseProduct, DatabaseProduct.POSTGRES_SQL)) {
                logger.debug("Using PostgresSqlStatementsSource");
                return new PostgresSqlStatementsSource(configuration);
            } else {
                logger.debug("Using SqlStatementsSource");
                return new SqlStatementsSource(configuration);
            }
        }
    }

    private static DatabaseProduct getDatabaseProduct(final Configuration configuration) {<FILL_FUNCTION_BODY>}

    @NonNull
    Map<String, Object> params(@NonNull LockConfiguration lockConfiguration) {
        return Map.of(
                "name",
                lockConfiguration.getName(),
                "lockUntil",
                timestamp(lockConfiguration.getLockAtMostUntil()),
                "now",
                timestamp(ClockProvider.now()),
                "lockedBy",
                configuration.getLockedByValue(),
                "unlockTime",
                timestamp(lockConfiguration.getUnlockTime()));
    }

    @NonNull
    private Object timestamp(Instant time) {
        TimeZone timeZone = configuration.getTimeZone();
        if (timeZone == null) {
            return Timestamp.from(time);
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(Date.from(time));
            calendar.setTimeZone(timeZone);
            return calendar;
        }
    }

    String getInsertStatement() {
        return "INSERT INTO " + tableName() + "(" + name() + ", " + lockUntil() + ", " + lockedAt() + ", " + lockedBy()
                + ") VALUES(:name, :lockUntil, :now, :lockedBy)";
    }

    public String getUpdateStatement() {
        return "UPDATE " + tableName() + " SET " + lockUntil() + " = :lockUntil, " + lockedAt() + " = :now, "
                + lockedBy() + " = :lockedBy WHERE " + name() + " = :name AND " + lockUntil() + " <= :now";
    }

    public String getExtendStatement() {
        return "UPDATE " + tableName() + " SET " + lockUntil() + " = :lockUntil WHERE " + name() + " = :name AND "
                + lockedBy() + " = :lockedBy AND " + lockUntil() + " > :now";
    }

    public String getUnlockStatement() {
        return "UPDATE " + tableName() + " SET " + lockUntil() + " = :unlockTime WHERE " + name() + " = :name";
    }

    String name() {
        return configuration.getColumnNames().getName();
    }

    String lockUntil() {
        return configuration.getColumnNames().getLockUntil();
    }

    String lockedAt() {
        return configuration.getColumnNames().getLockedAt();
    }

    String lockedBy() {
        return configuration.getColumnNames().getLockedBy();
    }

    String tableName() {
        return configuration.getTableName();
    }
}

        if (configuration.getDatabaseProduct() != null) {
            return configuration.getDatabaseProduct();
        }
        try {
            String jdbcProductName = configuration.getJdbcTemplate().execute((ConnectionCallback<String>)
                    connection -> connection.getMetaData().getDatabaseProductName());
            return DatabaseProduct.matchProductName(jdbcProductName);
        } catch (Exception e) {
            logger.debug("Can not determine database product name " + e.getMessage());
            return DatabaseProduct.UNKNOWN;
        }
    
<no_super_class>