All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.metadata.sql.SQLDatabase Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2015 HaiYang Li
 *
 * 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 com.landawn.abacus.metadata.sql;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.w3c.dom.Element;

import com.landawn.abacus.core.NameUtil;
import com.landawn.abacus.exception.UncheckedSQLException;
import com.landawn.abacus.metadata.Database;
import com.landawn.abacus.metadata.EntityDefXmlEle.DatabaseEle;
import com.landawn.abacus.metadata.EntityDefXmlEle.EntityDefEle.EntityEle.TableEle;
import com.landawn.abacus.metadata.Table;
import com.landawn.abacus.util.Configuration;
import com.landawn.abacus.util.ImmutableMap;
import com.landawn.abacus.util.JdbcUtil;
import com.landawn.abacus.util.XMLUtil;

// TODO: Auto-generated Javadoc
/**
 *
 * @author Haiyang Li
 * @since 0.8
 */
public class SQLDatabase implements Database {

    private static final String TABLE_NAME = "TABLE_NAME";

    private static final String TABLE = "TABLE";

    // private static final String REF_GENERATION = "REF_GENERATION";
    // private static final String USER = "USER";
    private static final String ORACLE = "ORACLE";

    private static final String BIN$ = "BIN$";

    private final String name;

    private final ImmutableMap attrs;

    private final ImmutableMap tableMap;

    public SQLDatabase(Connection conn, String dbName) {
        this(conn, dbName, null);
    }

    public SQLDatabase(Connection conn, String dbName, Collection selectTableNames) {
        this(conn, dbName, null, null, null, selectTableNames);
    }

    public SQLDatabase(Connection conn, String dbName, String schemaPattern, String tableNamePattern, String[] types) {
        this(conn, dbName, schemaPattern, tableNamePattern, types, null);
    }

    SQLDatabase(Connection conn, String dbName, String schemaPattern, String tableNamePattern, String[] types, Collection selectTableNames) {
        this(parse(conn, dbName, schemaPattern, tableNamePattern, types, selectTableNames));
    }

    public SQLDatabase(InputStream is) {
        this(Configuration.parse(is).getDocumentElement());
    }

    public SQLDatabase(Element databaseNode) {
        this(parse(databaseNode));
    }

    SQLDatabase(Object[] attrsTableMap) {
        this((Map) attrsTableMap[0], (Map) attrsTableMap[1]);
    }

    SQLDatabase(Map attrs, Map tableMap) {
        this.name = NameUtil.getCachedName(attrs.get(TableEle.NAME));
        attrs.put(TableEle.NAME, name);
        this.attrs = ImmutableMap.of(attrs);

        this.tableMap = ImmutableMap.of(tableMap);
    }

    /**
     * Gets the name.
     *
     * @return
     */
    @Override
    public String getName() {
        return name;
    }

    /**
     * Gets the product name.
     *
     * @return
     */
    @Override
    public String getProductName() {
        return attrs.get(DatabaseEle.PRODUCT_NAME);
    }

    /**
     * Gets the product version.
     *
     * @return
     */
    @Override
    public String getProductVersion() {
        return attrs.get(DatabaseEle.PRODUCT_VERSTION);
    }

    /**
     * Gets the table list.
     *
     * @return
     */
    @SuppressWarnings("rawtypes")
    @Override
    public Collection getTableList() {
        return (Collection) tableMap.values();
    }

    /**
     * Gets the table name list.
     *
     * @return
     */
    @Override
    public Collection getTableNameList() {
        return tableMap.keySet();
    }

    /**
     * Gets the table.
     *
     * @param tableName
     * @return
     */
    @Override
    public Table getTable(String tableName) {
        return tableMap.get(tableName);
    }

    /**
     * Gets the attributes.
     *
     * @return
     */
    @Override
    public Map getAttributes() {
        return attrs;
    }

    /**
     * Gets the attribute.
     *
     * @param attrName
     * @return
     */
    @Override
    public String getAttribute(String attrName) {
        return attrs.get(attrName);
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }

    /**
     *
     * @param obj
     * @return true, if successful
     */
    @Override
    public boolean equals(Object obj) {
        return this == obj || (obj instanceof SQLDatabase && ((SQLDatabase) obj).name.equals(name));
    }

    @Override
    public String toString() {
        return attrs.toString();
    }

    /**
     *
     * @param conn
     * @param dbName
     * @param schemaPattern
     * @param tableNamePattern
     * @param types
     * @param selectTableNames
     * @return
     */
    private static Object[] parse(Connection conn, String dbName, String schemaPattern, String tableNamePattern, String[] types,
            Collection selectTableNames) {
        final Map attrs = new LinkedHashMap<>();
        final Map tableMap = new LinkedHashMap<>();

        List tableNameList = new ArrayList<>();
        ResultSet rs = null;

        try {
            final DatabaseMetaData dmd = conn.getMetaData();

            attrs.put(DatabaseEle.NAME, dbName);
            attrs.put(DatabaseEle.PRODUCT_NAME, dmd.getDatabaseProductName());
            attrs.put(DatabaseEle.PRODUCT_VERSTION, dmd.getDatabaseProductVersion());

            if (types == null) {
                types = new String[] { TABLE };
            }

            rs = dmd.getTables(null, schemaPattern, tableNamePattern, types);

            while (rs.next()) {
                // if ((rs.getString(REF_GENERATION) != null) &&
                // !USER.equals(rs.getString(REF_GENERATION))) {
                // continue;
                // }
                String tableName = rs.getString(TABLE_NAME);

                // skip the tables in recycle bin for Oracle.
                if (tableName.toUpperCase().startsWith(BIN$) && dmd.getDatabaseProductName().toUpperCase().contains(ORACLE)) {
                    continue;
                }

                if (selectTableNames == null) {
                    tableNameList.add(tableName);
                } else {
                    for (String selectTableName : selectTableNames) {
                        if (tableName.equalsIgnoreCase(selectTableName) || tableName.matches(selectTableName)) {
                            tableNameList.add(tableName);

                            break;
                        }
                    }
                }
            }
        } catch (SQLException e) {
            throw new UncheckedSQLException(e);
        } finally {
            JdbcUtil.closeQuietly(rs);
        }

        for (int i = 0; i < tableNameList.size(); i++) {
            SQLTable table = new SQLTable(tableNameList.get(i), conn);
            tableMap.put(table.getName(), table);
        }

        return new Object[] { attrs, tableMap };
    }

    /**
     *
     * @param databaseNode
     * @return
     */
    private static Object[] parse(Element databaseNode) {
        final Map attrs = XMLUtil.readAttributes(databaseNode);
        final Map tableMap = new LinkedHashMap<>();

        final List tableElementList = XMLUtil.getElementsByTagName(databaseNode, TableEle.TABLE);
        for (Element tableElement : tableElementList) {
            SQLTable table = new SQLTable(tableElement);
            tableMap.put(table.getName(), table);
        }

        return new Object[] { attrs, tableMap };
    }
}