Package com.knowgate.datacopy

Source Code of com.knowgate.datacopy.DataTblDef

/*
  Copyright (C) 2003  Know Gate S.L. All rights reserved.
                      C/Oña, 107 1º2 28050 Madrid (Spain)

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.

  2. The end-user documentation included with the redistribution,
     if any, must include the following acknowledgment:
     "This product includes software parts from hipergate
     (http://www.hipergate.org/)."
     Alternately, this acknowledgment may appear in the software itself,
     if and wherever such third-party acknowledgments normally appear.

  3. The name hipergate must not be used to endorse or promote products
     derived from this software without prior written permission.
     Products derived from this software may not be called hipergate,
     nor may hipergate appear in their name, without prior written
     permission.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  You should have received a copy of hipergate License with this code;
  if not, visit http://www.hipergate.org or mail to info@hipergate.org
*/


package com.knowgate.datacopy;

import com.knowgate.debug.DebugFile;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.sql.SQLException;

/**
* <p>Keeps information about each table definition.</p>
* @author Sergio Montoro Ten
* @version 0.5 alpha
*/

public class DataTblDef {

  public DataTblDef() { }

  // ----------------------------------------------------------

  private void alloc(int cCols) {
    // Nº total de columnas en la tabla
    ColCount = cCols;
    // Array con los nombres de las columnas
    ColNames = new String[cCols];
    // Array con los tipos SQL de las columnas
    ColTypes = new int[cCols];
    // Array con las longitudes de las columnas
    ColSizes = new int[cCols];
    // Para cada columna, tiene true si forma parte de la PK, false en caso contrario
    PrimaryKeyMarks = new boolean[cCols];
    // Inicializar todos los campos por defecto a No-PK
    for (int c=0;c<cCols;c++) PrimaryKeyMarks[c] = false;
  }

  // ----------------------------------------------------------

  /**
   * Read table metadata
   * @param oConn JDBC Connection
   * @param sTable Table Name (case insensitive)
   * @param sPK List of primary key columns delimited by commas
   * @throws SQLException
   */
  public void readMetaData(Connection oConn, String sTable, String sPK) throws SQLException {
    int lenPK;
    int iCurr;
    int cCols;
    Statement oStmt = null;
    ResultSet oRSet = null;
    ResultSetMetaData oMDat = null;

    if (DebugFile.trace) {
      DebugFile.writeln("Begin DataTblDef.readMetaData([Connection], \"" + sTable + "\",\"" + sPK + "\")");
      DebugFile.incIdent();
    }

    BaseTable = sTable;

    // **********************************
    // * Leer los valores de metadatos

    // Lanza una SELECT que no devuelve ningún registro y luego
    // hace una llamada a getMetaData para guardar en memoria
    // la definición de los campos leidos.
    // La clave primaria no se extrae de la SELECT sino que debe
    // pasarse externamente como parametro.

    try {
      oStmt = oConn.createStatement();

      if (DebugFile.trace) DebugFile.writeln ("Statement.executeQuery(SELECT * FROM " + sTable + " WHERE 1=0)");

      oRSet = oStmt.executeQuery("SELECT * FROM " + sTable + " WHERE 1=0");

      oMDat = oRSet.getMetaData();

      cCols = oMDat.getColumnCount();

      alloc(cCols); // Función interna de soporte

      for (int c=0; c<cCols; c++) {
        ColNames[c] = oMDat.getColumnName(c+1);
        ColTypes[c] = oMDat.getColumnType(c+1);
        ColSizes[c] = oMDat.getPrecision(c+1);

        if (DebugFile.trace) DebugFile.writeln(ColNames[c] + " SQLType " + String.valueOf(ColTypes[c]) + " precision "  + ColSizes[c]);
      // next (c)

      oMDat = null;
    }
    catch (SQLException sqle) {
      throw new SQLException (sqle.getMessage(), sqle.getSQLState(), sqle.getErrorCode());
    }
    finally {
      if (null!=oRSet) oRSet.close();
      if (null!=oStmt) oStmt.close();
    }

    // *********************************************************
    // * Almacenar los nombres de campos de la clave primaria

    if (null!=sPK) {
      lenPK = sPK.length()-1;

      cPKs = 1;
      // Cuenta el nº de comas que hay en la cadena de entrada
      for (int i=1; i<=lenPK; i++)
        if(sPK.charAt(i)==',') cPKs++;

      // El nº de campos es la cantidad de comas mas uno
      PrimaryKeys = new String[cPKs];

      // Parsea la cadena de entrada usando las coma como indicador de salto
      iCurr = 0;
      PrimaryKeys[0] = "";
      for (int j=0; j<=lenPK; j++)
        if (sPK.charAt(j)!=',') {
          PrimaryKeys[iCurr] += sPK.charAt(j);
        }
        else {
          if (DebugFile.trace) DebugFile.writeln("PrimaryKeys[" + String.valueOf(iCurr) + "]=" + PrimaryKeys[iCurr]);
          PrimaryKeys[++iCurr] = "";
        }

      if (DebugFile.trace) DebugFile.writeln("PrimaryKeys[" + String.valueOf(iCurr) + "]=" + PrimaryKeys[iCurr]);

      // Almacenar un indicador booleano para cada campo que forme parte de la PK

      for (int l=0; l<ColCount; l++) PrimaryKeyMarks[l] = false;

      for (int k=0; k<cPKs; k++) {
        for (int f=0;f<ColCount;f++) {
          PrimaryKeyMarks[f] |= PrimaryKeys[k].equalsIgnoreCase(ColNames[f]);
        } // next (f)
      // next (k)
    } // end if (null!=sPK)
    else {
      cPKs = 0;
      PrimaryKeys = null;
      }

      if (DebugFile.trace) {
        DebugFile.decIdent();
        DebugFile.writeln("End DataTblDef.readMetaData()");
      }

  } // readMetaData ()

  // ---------------------------------------------------------------------------

  /**
   * Get table primary key
   * @param oConn JDBC Connection
   * @param sSchema String Schema name
   * @param sCatalog String Catalog Name
   * @param sTable String Table Name (case sensitive)
   * @return String List of table primary key columns delimited by commas, if table does not have a
   * primary key then return value is <b>null</b>
   * @throws SQLException
   */
  public String getPrimaryKeys (Connection oConn, String sSchema, String sCatalog, String sTable)
    throws SQLException {

    String sPKCols = null;
    DatabaseMetaData oMDat = oConn.getMetaData();
    ResultSet oRSet = oMDat.getPrimaryKeys(sCatalog, sSchema, sTable);

    while (oRSet.next()) {
      if (null==sPKCols)
        sPKCols = oRSet.getString(4);
      else
        sPKCols += "," + oRSet.getString(4);

    } // wend

    oRSet.close();

    return sPKCols;
  }

  // ----------------------------------------------------------

  public int findColumnPosition(String sColName) {
    // Busca la posición de una columna por nombre
    // Devuelve -1 si no la encuentra

    int iCol = -1;

    for (int c=0; (c<ColCount) && (iCol==-1); c++)
      if(sColName.equalsIgnoreCase(ColNames[c]))
        iCol = c;

    return iCol;
  } // findColumnPosition

  // ----------------------------------------------------------

  public int findColumnType(String sColName)  {
    // Busca el tipo de una columna por nombre
    // Devuelve 0 si no la encuentra

    int iType = 0;

    for (int c=0; c<ColCount; c++)
      if(sColName.equalsIgnoreCase(ColNames[c])) {
        iType = ColTypes[c];
        break;
      }
    return iType;
  } // findColumnType

  // ----------------------------------------------------------

  public boolean inheritsPK(DataTblDef oTblDef)
    throws ArrayIndexOutOfBoundsException {

    if (DebugFile.trace) {
      DebugFile.writeln("Begin " + BaseTable + " DataTblDef.inheritsPK(" + oTblDef.BaseTable + ")");
      DebugFile.incIdent();
      DebugFile.writeln(BaseTable + " has " + String.valueOf(cPKs) +" pk columns");
    }

    // Comprueba si dos DataTblDef tienen la misma estructura de tipos
    // y longitudes en sus campos de la PK y, por consiguiente, con
    // gran probabilidad un DataTblDef hereda la PK del otro.
    boolean bSamePK;
    int pc, fc;

    int iMatchCount = 0;

    if (DebugFile.trace)
      if (cPKs<oTblDef.cPKs)
        DebugFile.writeln(BaseTable + " does not inherit PK from " + oTblDef.BaseTable + " because " + oTblDef.BaseTable + " has " + String.valueOf(oTblDef.cPKs) + " PK columns and " + BaseTable + " has only " + String.valueOf(cPKs) + " PK columns");

    bSamePK = (cPKs>=oTblDef.cPKs);

    if (bSamePK) {

      for (int fk=0; fk<cPKs; fk++) {

        if (DebugFile.trace) DebugFile.writeln("fk=" + String.valueOf(fk));

        fc = findColumnPosition(PrimaryKeys[fk]);

        if (DebugFile.trace && -1==fc) DebugFile.writeln("cannot find column " + PrimaryKeys[fk] + " on " + BaseTable);

        if (-1!=fc) {

          for (int pk=0; pk<oTblDef.cPKs; pk++) {

            if (DebugFile.trace) DebugFile.writeln("pk=" + String.valueOf(pk));

            pc = oTblDef.findColumnPosition(oTblDef.PrimaryKeys[pk]);

            if (DebugFile.trace && -1==pc) DebugFile.writeln("cannot find column " + oTblDef.PrimaryKeys[pk] + " on " + oTblDef.BaseTable);

            if (-1!=pc) {

              if (DebugFile.trace)
                DebugFile.writeln("trying " + BaseTable + "." + ColNames[fc] + " and " + oTblDef.BaseTable + "." + oTblDef.ColNames[pc]);

              if ((oTblDef.ColTypes[pc]==ColTypes[fc] && oTblDef.ColSizes[pc]==ColSizes[fc]) &&
                 ((cPKs==1 && oTblDef.ColNames[pc].equalsIgnoreCase(ColNames[fc])) || (cPKs>1))) {

                if (DebugFile.trace) {
                  if (cPKs>1)
                    DebugFile.writeln(BaseTable + "." + PrimaryKeys[fk] + " matches " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[pk]);
                  else
                    DebugFile.writeln(BaseTable + "." + PrimaryKeys[fk] + " matches same column on " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[pk]);
                }

                iMatchCount++;
                break;
              }
              else {
                if (DebugFile.trace) {
                  if (oTblDef.ColTypes[pc]!=ColTypes[fc])
                    DebugFile.writeln(BaseTable + "." + PrimaryKeys[fk] + " has SQLType " + ColTypes[fc] + " and " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[pk] + " has SQLType " + oTblDef.ColTypes[pc]);
                  else if (oTblDef.ColSizes[pc]==ColSizes[fc])
                    DebugFile.writeln(BaseTable + "." + PrimaryKeys[fk] + " has size " + ColSizes[fc] + " and " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[pk] + " has size " + oTblDef.ColSizes[pc]);
                  else if (cPKs==1 && !oTblDef.ColNames[pc].equalsIgnoreCase(ColNames[fc]))
                    DebugFile.writeln(BaseTable + "." + PrimaryKeys[fk] + " as same SQLType and size as " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[pk] + " but it is not considered match because " + PrimaryKeys[fk] + " is a single primary key column and they don't have the same name");
                }
              }
            } // fi (-1!=pc)
          } // next (pk)
          if (iMatchCount==oTblDef.cPKs) break;

        } // fi (-1!=fc)
      } // next (fk)
    }

    if (DebugFile.trace) DebugFile.writeln("match count = " + String.valueOf(iMatchCount) + " , primary keys =" + String.valueOf(oTblDef.cPKs));

    if (iMatchCount<oTblDef.cPKs) bSamePK = false;

    if (DebugFile.trace) {
      DebugFile.decIdent();
      DebugFile.writeln("End DataTblDef.inheritsPK() : " + String.valueOf(bSamePK));
    }

    return bSamePK;
  } // inheritsPK

  // ----------------------------------------------------------

  public boolean bestMatch(int iThisCol, DataTblDef oTblDef, int iParentPK) {
    int[] aScores = new int[cPKs];
    int iPKPos;
    int iParentCol;
    int iPKRelativePos = 0;
    int iBestMatch = -1;
    int iBestScore = -1;

    if (DebugFile.trace) {
      DebugFile.writeln("Begin DataTblDef.bestMatch(" + BaseTable + "." + ColNames[iThisCol] + " , " + oTblDef.BaseTable + "." + oTblDef.PrimaryKeys[iParentPK] + ")");
      DebugFile.incIdent();
    }

    iParentCol = oTblDef.findColumnPosition(oTblDef.PrimaryKeys[iParentPK]);

    // Find seeked field relative position inside primary key
    for (int c=0; c<this.ColCount & iPKRelativePos<cPKs; c++)
      if (PrimaryKeyMarks[c] && !ColNames[c].equalsIgnoreCase(ColNames[iThisCol]))
        iPKRelativePos++;
      else if (PrimaryKeyMarks[c] && ColNames[c].equalsIgnoreCase(ColNames[iThisCol]))
        break;

    // For each key field, assign a score
    for (int k=0; k<cPKs; k++) {
      aScores[k] = 0;

      if (PrimaryKeys[k].equalsIgnoreCase(oTblDef.ColNames[iParentCol]))
        aScores[k] += 5; // Add 5 points if names match

      iPKPos = findColumnPosition(PrimaryKeys[k]);

      if (iPKPos>-1)
        if (ColTypes[iPKPos]==oTblDef.ColTypes[iParentCol] &&
            ColSizes[iPKPos]==oTblDef.ColSizes[iParentCol])
          aScores[k] += 1; // Add 1 point if types and sizes match
    } // next

    // Check if seeked field has the highest score
    for (int k=0; k<cPKs; k++) {
      if (aScores[k]>iBestScore) {
        iBestScore = aScores[k];
        iBestMatch = k;
      } // fi
    } // next

    if (DebugFile.trace) {
      DebugFile.writeln("pk relative position is " + String.valueOf(iPKRelativePos) + ", best match relative position is " + String.valueOf(iBestMatch));
      DebugFile.decIdent();
      DebugFile.writeln("End DataTblDef.bestMatch() : " + String.valueOf(iPKRelativePos==iBestMatch));
    }
    return (iPKRelativePos==iBestMatch);

  } // bestMatch

  // ----------------------------------------------------------

  public boolean isPrimaryKey(int iCol) {

    boolean bRetVal = PrimaryKeyMarks[iCol];

    return bRetVal;
  } // isPrimaryKey

  // ----------------------------------------------------------

  public boolean isPrimaryKey(String sCol) {
    boolean bRetVal;

    int iCol = findColumnPosition (sCol);

    if (-1==iCol)
      bRetVal = false;
    else
      bRetVal = PrimaryKeyMarks[iCol];

    return bRetVal;
  } // isPrimaryKey

  // *********************************************************
  // * Member Variables

  public int cPKs; // Nº total de campos en la PK
  public boolean bMayInheritPK;
  private boolean PrimaryKeyMarks[]; // Array con flags booleanos de PK / No-PK
  public String PrimaryKeys[]; // Nombre de los campos en la PK
  public String ColNames[]; // Nombres de todas las columnas (por orden de aparición)
  public int ColTypes[]; // Tipos de todas las columnas
  public int ColSizes[]; // Longitudes de todas las columnas
  public int ColCount; // Cuenta del nº total de columnas
  public String BaseTable;

  } // DataTblDef
TOP

Related Classes of com.knowgate.datacopy.DataTblDef

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.