/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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.ext.firebird; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.ext.firebird.model.FireBirdTrigger; import org.jkiss.dbeaver.ext.firebird.model.FireBirdTriggerType; import org.jkiss.dbeaver.ext.generic.model.*; import org.jkiss.dbeaver.model.DBPDataKind; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.DBUtils; import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.struct.rdb.DBSProcedureParameterKind; import org.jkiss.utils.CommonUtils; import org.osgi.framework.Version; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * FireBird utils */ public class FireBirdUtils { private static final Log log = Log.getLog(FireBirdUtils.class); public static String getProcedureSource(DBRProgressMonitor monitor, GenericProcedure procedure) throws DBException { try (JDBCSession session = DBUtils.openMetaSession(monitor, procedure.getDataSource(), "Load procedure source code")) { DatabaseMetaData fbMetaData = session.getOriginal().getMetaData(); String source = (String) fbMetaData.getClass().getMethod("getProcedureSourceCode", String.class).invoke(fbMetaData, procedure.getName()); if (CommonUtils.isEmpty(source)) { return null; } return getProcedureSourceWithHeader(monitor, procedure, source); } catch (SQLException e) { throw new DBException("Can't read source code of procedure '" + procedure.getName() + "'", e); } catch (Exception e) { log.debug(e); return null; } } public static String getViewSource(DBRProgressMonitor monitor, GenericTable view) throws DBException { try (JDBCSession session = DBUtils.openMetaSession(monitor, view.getDataSource(), "Load view source code")) { DatabaseMetaData fbMetaData = session.getOriginal().getMetaData(); String source = (String) fbMetaData.getClass().getMethod("getViewSourceCode", String.class).invoke(fbMetaData, view.getName()); if (CommonUtils.isEmpty(source)) { return null; } return getViewSourceWithHeader(monitor, view, source); } catch (SQLException e) { throw new DBException("Can't read source code of view '" + view.getName() + "'", e); } catch (Exception e) { log.debug(e); return null; } } public static String getTriggerSource(DBRProgressMonitor monitor, FireBirdTrigger trigger) throws DBException { try (JDBCSession session = DBUtils.openMetaSession(monitor, trigger.getDataSource(), "Load trigger source code")) { DatabaseMetaData fbMetaData = session.getOriginal().getMetaData(); String source = (String) fbMetaData.getClass().getMethod("getTriggerSourceCode", String.class).invoke(fbMetaData, trigger.getName()); if (CommonUtils.isEmpty(source)) { return null; } return getTriggerSourceWithHeader(monitor, trigger, source); } catch (SQLException e) { throw new DBException("Can't read source code of trigger '" + trigger.getName() + "'", e); } catch (Exception e) { log.debug(e); return null; } } public static String getProcedureSourceWithHeader(DBRProgressMonitor monitor, GenericProcedure procedure, String source) throws DBException { StringBuilder sql = new StringBuilder(); sql.append("CREATE OR ALTER PROCEDURE ").append(procedure.getName()).append(" "); Collection<GenericProcedureParameter> parameters = procedure.getParameters(monitor); if (parameters != null && !parameters.isEmpty()) { List<GenericProcedureParameter> args = new ArrayList<>(); List<GenericProcedureParameter> results = new ArrayList<>(); for (GenericProcedureParameter param : parameters) { if (param.getParameterKind() == DBSProcedureParameterKind.OUT || param.getParameterKind() == DBSProcedureParameterKind.RETURN) { results.add(param); } else { args.add(param); } } if (!args.isEmpty()) { sql.append("("); for (int i = 0; i < args.size(); i++) { GenericProcedureParameter param = args.get(i); if (i > 0) sql.append(", "); printParam(sql, param); } sql.append(")\n"); } if (!results.isEmpty()) { sql.append("RETURNS (\n"); for (int i = 0; i < results.size(); i++) { sql.append('\t'); GenericProcedureParameter param = results.get(i); printParam(sql, param); if (i < results.size() - 1) sql.append(","); sql.append('\n'); } sql.append(")\n"); } } sql.append("AS\n").append(source); return sql.toString(); } private static void printParam(StringBuilder sql, GenericProcedureParameter param) { sql.append(DBUtils.getQuotedIdentifier(param)).append(" ").append(param.getTypeName()); if (param.getDataKind() == DBPDataKind.STRING) { sql.append("(").append(param.getMaxLength()).append(")"); } } public static String getViewSourceWithHeader(DBRProgressMonitor monitor, GenericTable view, String source) throws DBException { Version version = getFireBirdServerVersion(view.getDataSource()); StringBuilder sql = new StringBuilder(); sql.append("CREATE "); if (version.getMajor() > 2 || (version.getMajor() == 2 && version.getMinor() >= 5)) { sql.append("OR ALTER "); } sql.append("VIEW ").append(view.getName()).append(" "); Collection<GenericTableColumn> columns = view.getAttributes(monitor); if (columns != null) { sql.append("("); boolean first = true; for (GenericTableColumn column : columns) { if (!first) { sql.append(", "); } first = false; sql.append(DBUtils.getQuotedIdentifier(column)); } sql.append(")\n"); } sql.append("AS\n").append(source); return sql.toString(); } public static String getTriggerSourceWithHeader(DBRProgressMonitor monitor, FireBirdTrigger trigger, String source) throws DBException { StringBuilder sql = new StringBuilder(); sql.append("CREATE TRIGGER ").append(trigger.getName()).append(" "); FireBirdTriggerType type = trigger.getType(); if (type.isDbEvent()) { sql.append(type.getDisplayName()); } else if (trigger.getTable() != null) { sql.append("FOR ").append(DBUtils.getQuotedIdentifier(trigger.getTable())); sql.append(" ").append(type.getDisplayName()); } sql.append("\n").append(source); return sql.toString(); } private static Pattern VERSION_PATTERN = Pattern.compile(".+\\-V([0-9]+\\.[0-9]+\\.[0-9]+).+"); public static Version getFireBirdServerVersion(DBPDataSource dataSource) { String versionInfo = dataSource.getInfo().getDatabaseProductVersion(); Matcher matcher = VERSION_PATTERN.matcher(versionInfo); if (matcher.matches()) { return new Version(matcher.group(1)); } return new Version(0, 0, 0); } }