0001: /*
0002: Copyright (C) 2003 Know Gate S.L. All rights reserved.
0003: C/Oña, 107 1º2 28050 Madrid (Spain)
0004:
0005: Redistribution and use in source and binary forms, with or without
0006: modification, are permitted provided that the following conditions
0007: are met:
0008:
0009: 1. Redistributions of source code must retain the above copyright
0010: notice, this list of conditions and the following disclaimer.
0011:
0012: 2. The end-user documentation included with the redistribution,
0013: if any, must include the following acknowledgment:
0014: "This product includes software parts from hipergate
0015: (http://www.hipergate.org/)."
0016: Alternately, this acknowledgment may appear in the software itself,
0017: if and wherever such third-party acknowledgments normally appear.
0018:
0019: 3. The name hipergate must not be used to endorse or promote products
0020: derived from this software without prior written permission.
0021: Products derived from this software may not be called hipergate,
0022: nor may hipergate appear in their name, without prior written
0023: permission.
0024:
0025: This library is distributed in the hope that it will be useful,
0026: but WITHOUT ANY WARRANTY; without even the implied warranty of
0027: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0028:
0029: You should have received a copy of hipergate License with this code;
0030: if not, visit http://www.hipergate.org or mail to info@hipergate.org
0031: */
0032:
0033: package com.knowgate.dataobjs;
0034:
0035: import java.io.IOException;
0036: import java.io.File;
0037: import java.io.InputStream;
0038: import java.io.ByteArrayInputStream;
0039: import java.io.StringBufferInputStream;
0040: import java.io.FileInputStream;
0041:
0042: import java.math.BigDecimal;
0043:
0044: import java.sql.SQLException;
0045: import java.sql.DatabaseMetaData;
0046: import java.sql.Connection;
0047: import java.sql.PreparedStatement;
0048: import java.sql.ResultSet;
0049: import java.sql.ResultSetMetaData;
0050: import java.sql.Statement;
0051: import java.sql.Timestamp;
0052: import java.sql.Types;
0053: import java.sql.ParameterMetaData;
0054:
0055: import java.util.HashMap;
0056: import java.util.LinkedList;
0057: import java.util.ListIterator;
0058:
0059: import com.knowgate.debug.*;
0060: import com.knowgate.jdc.*;
0061:
0062: /**
0063: * <p>A database table as a Java Object</p>
0064: * @author Sergio Montoro Ten
0065: * @version 3.0
0066: */
0067:
0068: public class DBTable {
0069:
0070: /**
0071: * <p>Constructor</p>
0072: * Catalog and schema names are set to <b>null</b>.<br>
0073: * Table index is set to 1.
0074: * @param sSchemaName Database schema name
0075: */
0076:
0077: public DBTable(String sTableName) {
0078: sCatalog = null;
0079: sSchema = null;
0080: sName = sTableName;
0081: iHashCode = 1;
0082: }
0083:
0084: /**
0085: * Constructor
0086: * @param sCatalogName Database catalog name
0087: * @param sSchemaName Database schema name
0088: * @param sTableName Database table name (not qualified)
0089: * @param iIndex Ordinal number identifier for table
0090: */
0091:
0092: public DBTable(String sCatalogName, String sSchemaName,
0093: String sTableName, int iIndex) {
0094: sName = sTableName;
0095: sCatalog = sCatalogName;
0096: sSchema = sSchemaName;
0097: iHashCode = iIndex;
0098: }
0099:
0100: // ---------------------------------------------------------------------------
0101:
0102: /**
0103: * @return Column Count for this table
0104: * @throws IllegalStateException if columns list has not been initialized
0105: */
0106:
0107: public int columnCount() throws IllegalStateException {
0108: if (null == oColumns)
0109: throw new IllegalStateException(
0110: "Table columns list not initialized");
0111: return oColumns.size();
0112: }
0113:
0114: // ---------------------------------------------------------------------------
0115:
0116: /**
0117: * <p>Load a single table register into a Java HashMap</p>
0118: * @param oConn Database Connection
0119: * @param PKValues Primary key values of register to be readed, in the same order as they appear in table source.
0120: * @param AllValues Output parameter. Readed values.
0121: * @return <b>true</b> if register was found <b>false</b> otherwise.
0122: * @throws NullPointerException If all objects in PKValues array are null (only debug version)
0123: * @throws IllegalStateException if columns list has not been initialized
0124: * @throws SQLException
0125: */
0126: public boolean loadRegister(JDCConnection oConn, Object[] PKValues,
0127: HashMap AllValues) throws SQLException,
0128: NullPointerException, IllegalStateException {
0129: int c;
0130: boolean bFound;
0131: Object oVal;
0132: DBColumn oDBCol;
0133: ListIterator oColIterator;
0134: PreparedStatement oStmt = null;
0135: ResultSet oRSet = null;
0136:
0137: if (null == oColumns)
0138: throw new IllegalStateException(
0139: "Table columns list not initialized");
0140:
0141: if (DebugFile.trace) {
0142: DebugFile
0143: .writeln("Begin DBTable.loadRegister([Connection], Object[], [HashMap])");
0144: DebugFile.incIdent();
0145:
0146: boolean bAllNull = true;
0147: for (int n = 0; n < PKValues.length; n++)
0148: bAllNull &= (PKValues[n] == null);
0149:
0150: if (bAllNull)
0151: throw new NullPointerException(
0152: sName
0153: + " cannot retrieve register, value supplied for primary key is NULL.");
0154: }
0155:
0156: if (sSelect == null) {
0157: throw new SQLException("Primary key not found", "42S12");
0158: }
0159:
0160: AllValues.clear();
0161:
0162: bFound = false;
0163:
0164: try {
0165:
0166: if (DebugFile.trace)
0167: DebugFile.writeln(" Connection.prepareStatement("
0168: + sSelect + ")");
0169:
0170: // Prepare SELECT sentence for reading
0171: oStmt = oConn.prepareStatement(sSelect);
0172:
0173: try {
0174: oStmt.setQueryTimeout(10);
0175: } catch (SQLException sqle) {
0176: if (DebugFile.trace)
0177: DebugFile
0178: .writeln("Error at PreparedStatement.setQueryTimeout(10)"
0179: + sqle.getMessage());
0180: }
0181:
0182: // Bind primary key values
0183: for (int p = 0; p < oPrimaryKeys.size(); p++) {
0184: if (DebugFile.trace)
0185: DebugFile.writeln(" binding primary key "
0186: + PKValues[p] + ".");
0187:
0188: oConn.bindParameter(oStmt, p + 1, PKValues[p]);
0189: //oStmt.setObject(p+1, PKValues[p]);
0190: } // next
0191:
0192: if (DebugFile.trace)
0193: DebugFile.writeln(" Connection.executeQuery()");
0194:
0195: oRSet = oStmt.executeQuery();
0196:
0197: if (oRSet.next()) {
0198: if (DebugFile.trace)
0199: DebugFile.writeln(" ResultSet.next()");
0200:
0201: bFound = true;
0202:
0203: // Iterate throught readed columns
0204: // and store readed values at AllValues
0205: oColIterator = oColumns.listIterator();
0206:
0207: c = 1;
0208: while (oColIterator.hasNext()) {
0209: oVal = oRSet.getObject(c++);
0210: oDBCol = (DBColumn) oColIterator.next();
0211: if (null != oVal)
0212: AllValues.put(oDBCol.getName(), oVal);
0213: }
0214: }
0215:
0216: if (DebugFile.trace)
0217: DebugFile.writeln(" ResultSet.close()");
0218:
0219: oRSet.close();
0220: oRSet = null;
0221:
0222: oStmt.close();
0223: oStmt = null;
0224: } catch (SQLException sqle) {
0225: try {
0226: if (null != oRSet)
0227: oRSet.close();
0228: if (null != oStmt)
0229: oStmt.close();
0230: } catch (Exception ignore) {
0231: }
0232:
0233: throw new SQLException(sqle.getMessage(), sqle
0234: .getSQLState(), sqle.getErrorCode());
0235: }
0236:
0237: if (DebugFile.trace) {
0238: DebugFile.decIdent();
0239: DebugFile.writeln("End DBTable.loadRegister() : "
0240: + (bFound ? "true" : "false"));
0241: }
0242:
0243: return bFound;
0244:
0245: } // loadRegister
0246:
0247: // ---------------------------------------------------------------------------
0248:
0249: /**
0250: * <p>Store a single register at the database representing a Java Object</p>
0251: * for register containing LONGVARBINARY, IMAGE, BYTEA or BLOB fields use
0252: * storeRegisterLong() method.
0253: * Columns named "dt_created" are invisible for storeRegister() method so that
0254: * register creation timestamp is not altered by afterwards updates.
0255: * @param oConn Database Connection
0256: * @param AllValues Values to assign to fields.
0257: * @return <b>true</b> if register was inserted for first time, <false> if it was updated.
0258: * @throws SQLException
0259: */
0260:
0261: public boolean storeRegister(JDCConnection oConn, HashMap AllValues)
0262: throws SQLException {
0263: int c;
0264: boolean bNewRow = false;
0265: DBColumn oCol;
0266: String sCol;
0267: String sSQL = "";
0268: ListIterator oColIterator;
0269: int iAffected = 0;
0270: PreparedStatement oStmt = null;
0271:
0272: if (DebugFile.trace) {
0273: DebugFile
0274: .writeln("Begin DBTable.storeRegister([Connection], {"
0275: + AllValues.toString() + "})");
0276: DebugFile.incIdent();
0277: }
0278:
0279: try {
0280: if (null != sUpdate) {
0281: if (DebugFile.trace)
0282: DebugFile.writeln("Connection.prepareStatement("
0283: + sUpdate + ")");
0284:
0285: sSQL = sUpdate;
0286:
0287: oStmt = oConn.prepareStatement(sSQL);
0288:
0289: try {
0290: oStmt.setQueryTimeout(10);
0291: } catch (SQLException sqle) {
0292: if (DebugFile.trace)
0293: DebugFile
0294: .writeln("Error at PreparedStatement.setQueryTimeout(10)"
0295: + sqle.getMessage());
0296: }
0297:
0298: c = 1;
0299: oColIterator = oColumns.listIterator();
0300:
0301: while (oColIterator.hasNext()) {
0302: oCol = (DBColumn) oColIterator.next();
0303: sCol = oCol.getName().toLowerCase();
0304:
0305: if (!oPrimaryKeys.contains(sCol)
0306: && (sCol.compareTo(DB.dt_created) != 0)) {
0307:
0308: if (DebugFile.trace) {
0309: if (oCol.getSqlType() == java.sql.Types.CHAR
0310: || oCol.getSqlType() == java.sql.Types.VARCHAR) {
0311:
0312: if (AllValues.get(sCol) != null) {
0313: DebugFile.writeln("Binding "
0314: + sCol
0315: + "="
0316: + AllValues.get(sCol)
0317: .toString());
0318:
0319: if (AllValues.get(sCol).toString()
0320: .length() > oCol
0321: .getPrecision())
0322: DebugFile
0323: .writeln("ERROR: value for "
0324: + oCol
0325: .getName()
0326: + " exceeds columns precision of "
0327: + String
0328: .valueOf(oCol
0329: .getPrecision()));
0330: } // fi (AllValues.get(sCol)!=null)
0331: else
0332: DebugFile.writeln("Binding " + sCol
0333: + "=NULL");
0334: }
0335: } // fi (DebugFile.trace)
0336:
0337: try {
0338: oConn.bindParameter(oStmt, c, AllValues
0339: .get(sCol), oCol.getSqlType());
0340: c++;
0341: } catch (ClassCastException e) {
0342: if (AllValues.get(sCol) != null)
0343: throw new SQLException(
0344: "ClassCastException at column "
0345: + sCol
0346: + " Cannot cast Java "
0347: + AllValues.get(sCol)
0348: .getClass()
0349: .getName()
0350: + " to SQL type "
0351: + oCol.getSqlTypeName(),
0352: "07006");
0353: else
0354: throw new SQLException(
0355: "ClassCastException at column "
0356: + sCol
0357: + " Cannot cast NULL to SQL type "
0358: + oCol.getSqlTypeName(),
0359: "07006");
0360: }
0361:
0362: } // endif (!oPrimaryKeys.contains(sCol))
0363: } // wend
0364:
0365: oColIterator = oPrimaryKeys.listIterator();
0366: while (oColIterator.hasNext()) {
0367: sCol = (String) oColIterator.next();
0368: oCol = getColumnByName(sCol);
0369:
0370: if (DebugFile.trace)
0371: DebugFile
0372: .writeln("PreparedStatement.setObject ("
0373: + String.valueOf(c)
0374: + ","
0375: + AllValues.get(sCol)
0376: + ","
0377: + oCol.getSqlTypeName() + ")");
0378:
0379: oConn.bindParameter(oStmt, c, AllValues.get(sCol),
0380: oCol.getSqlType());
0381: c++;
0382: } // wend
0383:
0384: if (DebugFile.trace)
0385: DebugFile
0386: .writeln("PreparedStatement.executeUpdate()");
0387:
0388: iAffected = oStmt.executeUpdate();
0389:
0390: if (DebugFile.trace)
0391: DebugFile.writeln(String.valueOf(iAffected)
0392: + " affected rows");
0393:
0394: oStmt.close();
0395: oStmt = null;
0396: } // fi (sUpdate!=null)
0397: else
0398: iAffected = 0;
0399:
0400: if (0 == iAffected) {
0401: bNewRow = true;
0402:
0403: if (DebugFile.trace)
0404: DebugFile.writeln("Connection.prepareStatement("
0405: + sInsert + ")");
0406:
0407: sSQL = sInsert;
0408:
0409: oStmt = oConn.prepareStatement(sInsert);
0410:
0411: try {
0412: oStmt.setQueryTimeout(10);
0413: } catch (SQLException sqle) {
0414: if (DebugFile.trace)
0415: DebugFile
0416: .writeln("Error at PreparedStatement.setQueryTimeout(10)"
0417: + sqle.getMessage());
0418: }
0419:
0420: c = 1;
0421: oColIterator = oColumns.listIterator();
0422:
0423: while (oColIterator.hasNext()) {
0424:
0425: oCol = (DBColumn) oColIterator.next();
0426: sCol = oCol.getName();
0427:
0428: if (DebugFile.trace) {
0429: if (null != AllValues.get(sCol))
0430: DebugFile.writeln("Binding " + sCol + "="
0431: + AllValues.get(sCol).toString());
0432: else
0433: DebugFile.writeln("Binding " + sCol
0434: + "=NULL");
0435: } // fi
0436:
0437: oConn.bindParameter(oStmt, c, AllValues.get(sCol),
0438: oCol.getSqlType());
0439: c++;
0440: } // wend
0441:
0442: if (DebugFile.trace)
0443: DebugFile
0444: .writeln("PreparedStatement.executeUpdate()");
0445:
0446: iAffected = oStmt.executeUpdate();
0447:
0448: if (DebugFile.trace)
0449: DebugFile.writeln(String.valueOf(iAffected)
0450: + " affected rows");
0451:
0452: oStmt.close();
0453: oStmt = null;
0454: } else
0455: bNewRow = false;
0456: } catch (SQLException sqle) {
0457: try {
0458: if (null != oStmt)
0459: oStmt.close();
0460: } catch (Exception ignore) {
0461: }
0462:
0463: throw new SQLException(sqle.getMessage() + " " + sSQL, sqle
0464: .getSQLState(), sqle.getErrorCode());
0465: }
0466:
0467: if (DebugFile.trace) {
0468: DebugFile.decIdent();
0469: DebugFile.writeln("End DBTable.storeRegister() : "
0470: + String.valueOf(bNewRow && (iAffected > 0)));
0471: }
0472:
0473: return bNewRow && (iAffected > 0);
0474: } // storeRegister
0475:
0476: // ---------------------------------------------------------------------------
0477:
0478: /**
0479: * <p>Store a single register at the database representing a Java Object</p>
0480: * for register NOT containing LONGVARBINARY, IMAGE, BYTEA or BLOB fields use
0481: * storeRegister() method witch is faster than storeRegisterLong().
0482: * Columns named "dt_created" are invisible for storeRegisterLong() method so that
0483: * register creation timestamp is not altered by afterwards updates.
0484: * @param oConn Database Connection
0485: * @param AllValues Values to assign to fields.
0486: * @param BinaryLengths map of lengths for long fields.
0487: * @return <b>true</b> if register was inserted for first time, <false> if it was updated.
0488: * @throws SQLException
0489: */
0490:
0491: public boolean storeRegisterLong(JDCConnection oConn,
0492: HashMap AllValues, HashMap BinaryLengths)
0493: throws IOException, SQLException {
0494: int c;
0495: boolean bNewRow = false;
0496: DBColumn oCol;
0497: String sCol;
0498: ListIterator oColIterator;
0499: PreparedStatement oStmt;
0500: int iAffected;
0501:
0502: LinkedList oStreams;
0503: InputStream oStream;
0504: String sClassName;
0505:
0506: if (DebugFile.trace) {
0507: DebugFile
0508: .writeln("Begin DBTable.storeRegisterLong([Connection], {"
0509: + AllValues.toString() + "})");
0510: DebugFile.incIdent();
0511: }
0512:
0513: oStreams = new LinkedList();
0514:
0515: if (null != sUpdate) {
0516:
0517: if (DebugFile.trace)
0518: DebugFile.writeln("Connection.prepareStatement("
0519: + sUpdate + ")");
0520:
0521: oStmt = oConn.prepareStatement(sUpdate);
0522:
0523: try {
0524: oStmt.setQueryTimeout(10);
0525: } catch (SQLException sqle) {
0526: if (DebugFile.trace)
0527: DebugFile
0528: .writeln("Error at PreparedStatement.setQueryTimeout(10)"
0529: + sqle.getMessage());
0530: }
0531:
0532: c = 1;
0533: oColIterator = oColumns.listIterator();
0534: while (oColIterator.hasNext()) {
0535: oCol = (DBColumn) oColIterator.next();
0536: sCol = oCol.getName().toLowerCase();
0537:
0538: if (!oPrimaryKeys.contains(sCol)
0539: && (!sCol.equalsIgnoreCase(DB.dt_created))) {
0540:
0541: if (DebugFile.trace) {
0542: if (oCol.getSqlType() == java.sql.Types.CHAR
0543: || oCol.getSqlType() == java.sql.Types.VARCHAR) {
0544: if (AllValues.get(sCol) != null) {
0545: DebugFile.writeln("Binding "
0546: + sCol
0547: + "="
0548: + AllValues.get(sCol)
0549: .toString());
0550: if (AllValues.get(sCol).toString()
0551: .length() > oCol.getPrecision())
0552: DebugFile
0553: .writeln("ERROR: value for "
0554: + oCol.getName()
0555: + " exceeds columns precision of "
0556: + String
0557: .valueOf(oCol
0558: .getPrecision()));
0559: } // fi (AllValues.get(sCol)!=null)
0560: else
0561: DebugFile.writeln("Binding " + sCol
0562: + "=NULL");
0563: }
0564: } // fi (DebugFile.trace)
0565:
0566: if (oCol.getSqlType() == java.sql.Types.LONGVARCHAR
0567: || oCol.getSqlType() == java.sql.Types.CLOB
0568: || oCol.getSqlType() == java.sql.Types.LONGVARBINARY
0569: || oCol.getSqlType() == java.sql.Types.BLOB) {
0570: if (BinaryLengths.containsKey(sCol)) {
0571: if (((Long) BinaryLengths.get(sCol))
0572: .intValue() > 0) {
0573: sClassName = AllValues.get(sCol)
0574: .getClass().getName();
0575: if (sClassName.equals("java.io.File"))
0576: oStream = new FileInputStream(
0577: (File) AllValues.get(sCol));
0578: else if (sClassName.equals("[B"))
0579: oStream = new ByteArrayInputStream(
0580: (byte[]) AllValues
0581: .get(sCol));
0582: else if (sClassName.equals("[C"))
0583: oStream = new StringBufferInputStream(
0584: new String(
0585: (char[]) AllValues
0586: .get(sCol)));
0587: else
0588: throw new SQLException(
0589: "Invalid object binding for column "
0590: + sCol);
0591: oStreams.addLast(oStream);
0592: oStmt
0593: .setBinaryStream(c++, oStream,
0594: ((Long) BinaryLengths
0595: .get(sCol))
0596: .intValue());
0597: } else
0598: oStmt.setObject(c++, null, oCol
0599: .getSqlType());
0600: } else
0601: oStmt.setObject(c++, null, oCol
0602: .getSqlType());
0603: } else
0604: oConn.bindParameter(oStmt, c++, AllValues
0605: .get(sCol), oCol.getSqlType());
0606: } // fi (!oPrimaryKeys.contains(sCol))
0607: } // wend
0608:
0609: oColIterator = oPrimaryKeys.listIterator();
0610: while (oColIterator.hasNext()) {
0611: sCol = (String) oColIterator.next();
0612: oCol = getColumnByName(sCol);
0613:
0614: if (DebugFile.trace)
0615: DebugFile.writeln("PreparedStatement.setObject ("
0616: + String.valueOf(c) + ","
0617: + AllValues.get(sCol) + ","
0618: + oCol.getSqlTypeName() + ")");
0619:
0620: oConn.bindParameter(oStmt, c, AllValues.get(sCol), oCol
0621: .getSqlType());
0622: c++;
0623: } // wend
0624:
0625: if (DebugFile.trace)
0626: DebugFile.writeln("PreparedStatement.executeUpdate()");
0627:
0628: iAffected = oStmt.executeUpdate();
0629:
0630: if (DebugFile.trace)
0631: DebugFile.writeln(String.valueOf(iAffected)
0632: + " affected rows");
0633:
0634: oStmt.close();
0635:
0636: oColIterator = oStreams.listIterator();
0637:
0638: while (oColIterator.hasNext())
0639: ((InputStream) oColIterator.next()).close();
0640:
0641: oStreams.clear();
0642:
0643: } else
0644: iAffected = 0;
0645:
0646: if (0 == iAffected) {
0647: bNewRow = true;
0648:
0649: if (DebugFile.trace)
0650: DebugFile.writeln("Connection.prepareStatement("
0651: + sInsert + ")");
0652:
0653: oStmt = oConn.prepareStatement(sInsert);
0654:
0655: c = 1;
0656: oColIterator = oColumns.listIterator();
0657:
0658: while (oColIterator.hasNext()) {
0659:
0660: oCol = (DBColumn) oColIterator.next();
0661: sCol = oCol.getName();
0662:
0663: if (DebugFile.trace) {
0664: if (null != AllValues.get(sCol))
0665: DebugFile.writeln("Binding " + sCol + "="
0666: + AllValues.get(sCol).toString());
0667: else
0668: DebugFile.writeln("Binding " + sCol + "=NULL");
0669: }
0670:
0671: if (oCol.getSqlType() == java.sql.Types.LONGVARCHAR
0672: || oCol.getSqlType() == java.sql.Types.CLOB
0673: || oCol.getSqlType() == java.sql.Types.LONGVARBINARY
0674: || oCol.getSqlType() == java.sql.Types.BLOB) {
0675: if (BinaryLengths.containsKey(sCol)) {
0676: if (((Long) BinaryLengths.get(sCol)).intValue() > 0) {
0677: sClassName = AllValues.get(sCol).getClass()
0678: .getName();
0679: if (sClassName.equals("java.io.File"))
0680: oStream = new FileInputStream(
0681: (File) AllValues.get(sCol));
0682: else if (sClassName.equals("[B"))
0683: oStream = new ByteArrayInputStream(
0684: (byte[]) AllValues.get(sCol));
0685: else if (sClassName.equals("[C"))
0686: oStream = new StringBufferInputStream(
0687: new String((char[]) AllValues
0688: .get(sCol)));
0689: else
0690: throw new SQLException(
0691: "Invalid object binding for column "
0692: + sCol);
0693: oStreams.addLast(oStream);
0694: oStmt.setBinaryStream(c++, oStream,
0695: ((Long) BinaryLengths.get(sCol))
0696: .intValue());
0697: } else
0698: oStmt.setObject(c++, null, oCol
0699: .getSqlType());
0700: } else
0701: oStmt.setObject(c++, null, oCol.getSqlType());
0702: } else
0703: oConn.bindParameter(oStmt, c++,
0704: AllValues.get(sCol), oCol.getSqlType());
0705: } // wend
0706:
0707: if (DebugFile.trace)
0708: DebugFile.writeln("PreparedStatement.executeUpdate()");
0709:
0710: iAffected = oStmt.executeUpdate();
0711:
0712: if (DebugFile.trace)
0713: DebugFile.writeln(String.valueOf(iAffected)
0714: + " affected rows");
0715:
0716: oStmt.close();
0717:
0718: oColIterator = oStreams.listIterator();
0719:
0720: while (oColIterator.hasNext())
0721: ((InputStream) oColIterator.next()).close();
0722:
0723: oStreams.clear();
0724: }
0725:
0726: else
0727: bNewRow = false;
0728:
0729: // End SQLException
0730:
0731: if (DebugFile.trace) {
0732: DebugFile.decIdent();
0733: DebugFile.writeln("End DBTable.storeRegisterLong() : "
0734: + String.valueOf(bNewRow));
0735: }
0736:
0737: return bNewRow;
0738: } // storeRegisterLong
0739:
0740: // ---------------------------------------------------------------------------
0741:
0742: /**
0743: * <p>Delete a single register from this table at the database</p>
0744: * @param oConn Database connection
0745: * @param AllValues A Map with, at least, the primary key values for the register. Other Map values are ignored.
0746: * @return <b>true</b> if register was delete, <b>false</b> if register to be deleted was not found.
0747: * @throws SQLException
0748: */
0749:
0750: public boolean deleteRegister(JDCConnection oConn, HashMap AllValues)
0751: throws SQLException {
0752: int c;
0753: boolean bDeleted;
0754: ListIterator oColIterator;
0755: PreparedStatement oStmt;
0756: Object oPK;
0757: DBColumn oCol;
0758:
0759: if (DebugFile.trace) {
0760: DebugFile
0761: .writeln("Begin DBTable.deleteRegister([Connection], {"
0762: + AllValues.toString() + "})");
0763: DebugFile.incIdent();
0764: }
0765:
0766: if (sDelete == null) {
0767: throw new SQLException("Primary key not found", "42S12");
0768: }
0769:
0770: // Begin SQLException
0771:
0772: if (DebugFile.trace)
0773: DebugFile.writeln("Connection.prepareStatement(" + sDelete
0774: + ")");
0775:
0776: oStmt = oConn.prepareStatement(sDelete);
0777:
0778: c = 1;
0779: oColIterator = oPrimaryKeys.listIterator();
0780:
0781: while (oColIterator.hasNext()) {
0782: oPK = oColIterator.next();
0783: oCol = getColumnByName((String) oPK);
0784:
0785: if (DebugFile.trace)
0786: DebugFile.writeln("PreparedStatement.setObject("
0787: + String.valueOf(c) + "," + AllValues.get(oPK)
0788: + "," + oCol.getSqlTypeName() + ")");
0789:
0790: oStmt.setObject(c++, AllValues.get(oPK), oCol.getSqlType());
0791: } // wend
0792:
0793: if (DebugFile.trace)
0794: DebugFile.writeln("PreparedStatement.executeUpdate()");
0795:
0796: bDeleted = (oStmt.executeUpdate() > 0);
0797:
0798: // End SQLException
0799:
0800: if (DebugFile.trace) {
0801: DebugFile.decIdent();
0802: DebugFile.writeln("End DBTable.deleteRegister() : "
0803: + (bDeleted ? "true" : "false"));
0804: }
0805:
0806: return bDeleted;
0807: } // deleteRegister
0808:
0809: // ---------------------------------------------------------------------------
0810:
0811: /**
0812: * <p>Checks if register exists at this table</p>
0813: * @param oConn Database Connection
0814: * @param sQueryString Register Query String, as a SQL WHERE clause syntax
0815: * @return <b>true</b> if register exists, <b>false</b> otherwise.
0816: * @throws SQLException
0817: */
0818:
0819: public boolean existsRegister(JDCConnection oConn,
0820: String sQueryString) throws SQLException {
0821: Statement oStmt = oConn
0822: .createStatement(ResultSet.TYPE_FORWARD_ONLY,
0823: ResultSet.CONCUR_READ_ONLY);
0824:
0825: ResultSet oRSet = oStmt.executeQuery("SELECT NULL FROM "
0826: + getName() + " WHERE " + sQueryString);
0827: boolean bExists = oRSet.next();
0828: oRSet.close();
0829: oStmt.close();
0830:
0831: return bExists;
0832: }
0833:
0834: // ---------------------------------------------------------------------------
0835:
0836: /**
0837: * <p>Checks if register exists at this table</p>
0838: * @param oConn Database Connection
0839: * @param sQueryString Register Query String, as a SQL WHERE clause syntax
0840: * @return <b>true</b> if register exists, <b>false</b> otherwise.
0841: * @throws SQLException
0842: */
0843:
0844: public boolean existsRegister(JDCConnection oConn,
0845: String sQueryString, Object[] oQueryParams)
0846: throws SQLException {
0847: PreparedStatement oStmt = oConn.prepareStatement(
0848: "SELECT NULL FROM " + getName() + " WHERE "
0849: + sQueryString, ResultSet.TYPE_FORWARD_ONLY,
0850: ResultSet.CONCUR_READ_ONLY);
0851:
0852: if (oQueryParams != null) {
0853: for (int p = 0; p < oQueryParams.length; p++)
0854: oStmt.setObject(p + 1, oQueryParams[p]);
0855: }
0856:
0857: ResultSet oRSet = oStmt.executeQuery();
0858: boolean bExists = oRSet.next();
0859: oRSet.close();
0860: oStmt.close();
0861:
0862: return bExists;
0863: }
0864:
0865: // ---------------------------------------------------------------------------
0866:
0867: /**
0868: * <p>Checks if register exists at this table</p>
0869: * @param oConn Database Connection
0870: * @return <b>true</b> if register exists, <b>false</b> otherwise.
0871: * @throws SQLException
0872: */
0873:
0874: public boolean existsRegister(JDCConnection oConn, HashMap AllValues)
0875: throws SQLException {
0876: int c;
0877: boolean bExists;
0878: PreparedStatement oStmt;
0879: ResultSet oRSet;
0880: ListIterator oColIterator;
0881: Object oPK;
0882: DBColumn oCol;
0883:
0884: if (DebugFile.trace) {
0885: DebugFile
0886: .writeln("Begin DBTable.existsRegister([Connection], {"
0887: + AllValues.toString() + "})");
0888: DebugFile.incIdent();
0889: }
0890:
0891: oStmt = oConn
0892: .prepareStatement(sExists, ResultSet.TYPE_FORWARD_ONLY,
0893: ResultSet.CONCUR_READ_ONLY);
0894:
0895: c = 1;
0896: oColIterator = oPrimaryKeys.listIterator();
0897:
0898: while (oColIterator.hasNext()) {
0899: oPK = oColIterator.next();
0900: oCol = getColumnByName((String) oPK);
0901:
0902: oStmt.setObject(c++, AllValues.get(oPK), oCol.getSqlType());
0903: } // wend
0904:
0905: oRSet = oStmt.executeQuery();
0906: bExists = oRSet.next();
0907:
0908: oRSet.close();
0909: oStmt.close();
0910:
0911: if (DebugFile.trace) {
0912: DebugFile.decIdent();
0913: DebugFile.writeln("End DBTable.existsRegister() : "
0914: + String.valueOf(bExists));
0915: }
0916:
0917: return bExists;
0918: } // existsRegister
0919:
0920: // ---------------------------------------------------------------------------
0921:
0922: /**
0923: * @return List of {@link DBColumn} objects composing this table.
0924: */
0925:
0926: public LinkedList getColumns() {
0927: return oColumns;
0928: }
0929:
0930: // ---------------------------------------------------------------------------
0931:
0932: /**
0933: * @return Columns names separated by commas
0934: * @throws IllegalStateException
0935: */
0936:
0937: public String getColumnsStr() throws IllegalStateException {
0938:
0939: if (null == oColumns)
0940: throw new IllegalStateException(
0941: "Table columns list has not been initialized");
0942:
0943: ListIterator oColIterator = oColumns.listIterator();
0944: String sGetAllCols = new String("");
0945:
0946: while (oColIterator.hasNext())
0947: sGetAllCols += ((DBColumn) oColIterator.next()).getName()
0948: + ",";
0949:
0950: return sGetAllCols.substring(0, sGetAllCols.length() - 1);
0951:
0952: } // getColumnsStr
0953:
0954: // ---------------------------------------------------------------------------
0955:
0956: /**
0957: * <p>Get DBColumn by name</p>
0958: * @param sColumnName Column Name
0959: * @return Reference to DBColumn ot <b>null</b> if no column with such name was found.
0960: * @throws IllegalStateException If column list for table has not been initialized
0961: */
0962:
0963: public DBColumn getColumnByName(String sColumnName)
0964: throws IllegalStateException {
0965:
0966: if (null == oColumns)
0967: throw new IllegalStateException(
0968: "Table columns list not initialized");
0969:
0970: ListIterator oColIterator = oColumns.listIterator();
0971: DBColumn oCol = null;
0972:
0973: while (oColIterator.hasNext()) {
0974: oCol = (DBColumn) oColIterator.next();
0975: if (oCol.getName().equalsIgnoreCase(sColumnName)) {
0976: break;
0977: }
0978: oCol = null;
0979: } // wend
0980:
0981: return oCol;
0982:
0983: } // getColumnByName
0984:
0985: // ---------------------------------------------------------------------------
0986:
0987: /**
0988: * <p>Get DBColumn index given its by name</p>
0989: * @param sColumnName Column Name
0990: * @return Column Index[1..columnsCount()] or -1 if no column with such name was found.
0991: */
0992:
0993: public int getColumnIndex(String sColumnName) {
0994: ListIterator oColIterator = oColumns.listIterator();
0995: DBColumn oCol = null;
0996:
0997: while (oColIterator.hasNext()) {
0998: oCol = (DBColumn) oColIterator.next();
0999: if (oCol.getName().equalsIgnoreCase(sColumnName)) {
1000: return oCol.getPosition();
1001: }
1002: oCol = null;
1003: } // wend
1004:
1005: return -1;
1006:
1007: } // getColumnIndex
1008:
1009: // ---------------------------------------------------------------------------
1010:
1011: /**
1012: * @return List of primary key column names
1013: */
1014:
1015: public LinkedList getPrimaryKey() {
1016: return oPrimaryKeys;
1017:
1018: }
1019:
1020: // ---------------------------------------------------------------------------
1021:
1022: /**
1023: * @return Unqualified table name
1024: */
1025:
1026: public String getName() {
1027: return sName;
1028: }
1029:
1030: // ---------------------------------------------------------------------------
1031:
1032: /**
1033: * @return Catalog name
1034: */
1035:
1036: public String getCatalog() {
1037: return sCatalog;
1038: }
1039:
1040: // ---------------------------------------------------------------------------
1041:
1042: public void setCatalog(String sCatalogName) {
1043: sCatalog = sCatalogName;
1044: }
1045:
1046: // ---------------------------------------------------------------------------
1047:
1048: /**
1049: * @return Schema name
1050: */
1051:
1052: public String getSchema() {
1053: return sSchema;
1054: }
1055:
1056: // ---------------------------------------------------------------------------
1057:
1058: /**
1059: * Set schema name
1060: * @param sSchemaName String
1061: */
1062: public void setSchema(String sSchemaName) {
1063: sSchema = sSchemaName;
1064: }
1065:
1066: // ---------------------------------------------------------------------------
1067:
1068: public int hashCode() {
1069: return iHashCode;
1070: }
1071:
1072: // ---------------------------------------------------------------------------
1073:
1074: /**
1075: * <p>Read DBColumn List from DatabaseMetaData</p>
1076: * This is primarily an internal initialization method for DBTable object.
1077: * Usually there is no need to call it from any other class.
1078: * @param oConn Database Connection
1079: * @param oMData DatabaseMetaData
1080: * @throws SQLException
1081: */
1082: public void readColumns(Connection oConn, DatabaseMetaData oMData)
1083: throws SQLException {
1084: int iErrCode;
1085: Statement oStmt;
1086: ResultSet oRSet;
1087: ResultSetMetaData oRData;
1088: DBColumn oCol;
1089: String sCol;
1090: int iCols;
1091: ListIterator oColIterator;
1092:
1093: String sColName;
1094: short iSQLType;
1095: String sTypeName;
1096: int iPrecision;
1097: int iDigits;
1098: int iNullable;
1099: int iColPos;
1100:
1101: int iDBMS;
1102:
1103: String sGetAllCols = "";
1104: String sSetPKCols = "";
1105: String sSetAllCols = "";
1106: String sSetNoPKCols = "";
1107:
1108: oColumns = new LinkedList();
1109: oPrimaryKeys = new LinkedList();
1110:
1111: if (DebugFile.trace) {
1112: DebugFile
1113: .writeln("Begin DBTable.readColumns([DatabaseMetaData])");
1114: DebugFile.incIdent();
1115:
1116: DebugFile.writeln("DatabaseMetaData.getColumns(" + sCatalog
1117: + "," + sSchema + "," + sName + ",%)");
1118: }
1119:
1120: if (oConn.getMetaData().getDatabaseProductName().equals(
1121: "PostgreSQL"))
1122: iDBMS = JDCConnection.DBMS_POSTGRESQL;
1123: else if (oConn.getMetaData().getDatabaseProductName().equals(
1124: "Oracle"))
1125: iDBMS = JDCConnection.DBMS_ORACLE;
1126: else
1127: iDBMS = 0;
1128:
1129: oStmt = oConn.createStatement();
1130:
1131: try {
1132: if (DebugFile.trace)
1133: DebugFile
1134: .writeln("Statement.executeQuery(SELECT * FROM "
1135: + sName + " WHERE 1=0)");
1136:
1137: oRSet = oStmt.executeQuery("SELECT * FROM " + sName
1138: + " WHERE 1=0");
1139: iErrCode = 0;
1140: } catch (SQLException sqle) {
1141: // Patch for Oracle. DatabaseMetadata.getTables() returns table names
1142: // that later cannot be SELECTed, so this catch ignore these system tables
1143:
1144: oStmt.close();
1145: oRSet = null;
1146:
1147: if (DebugFile.trace)
1148: DebugFile.writeln("SQLException " + sName + " "
1149: + sqle.getMessage());
1150:
1151: iErrCode = sqle.getErrorCode();
1152: if (iErrCode == 0)
1153: iErrCode = -1;
1154: if (!sqle.getSQLState().equals("42000"))
1155: throw new SQLException(sqle.getMessage(), sqle
1156: .getSQLState(), sqle.getErrorCode());
1157: }
1158:
1159: if (0 == iErrCode) {
1160: if (DebugFile.trace)
1161: DebugFile.writeln("ResultSet.getMetaData()");
1162:
1163: oRData = oRSet.getMetaData();
1164:
1165: iCols = oRData.getColumnCount();
1166:
1167: if (DebugFile.trace)
1168: DebugFile.writeln("table has " + String.valueOf(iCols)
1169: + " columns");
1170:
1171: for (int c = 1; c <= iCols; c++) {
1172: sColName = oRData.getColumnName(c).toLowerCase();
1173: sTypeName = oRData.getColumnTypeName(c);
1174: iSQLType = (short) oRData.getColumnType(c);
1175:
1176: if (iDBMS == JDCConnection.DBMS_POSTGRESQL)
1177: switch (iSQLType) {
1178: case Types.CHAR:
1179: case Types.VARCHAR:
1180: iPrecision = oRData.getColumnDisplaySize(c);
1181: break;
1182: default:
1183: iPrecision = oRData.getPrecision(c);
1184: }
1185: else {
1186: // New for v2.0, solves bug SF887614
1187: if (iSQLType == Types.BLOB
1188: || iSQLType == Types.CLOB)
1189: iPrecision = 2147483647;
1190: // end v2.0
1191: else
1192: iPrecision = oRData.getPrecision(c);
1193: }
1194:
1195: iDigits = oRData.getScale(c);
1196: iNullable = oRData.isNullable(c);
1197: iColPos = c;
1198:
1199: if (5 == iDBMS && iSQLType == Types.NUMERIC
1200: && iPrecision <= 6 && iDigits == 0) {
1201: // Workaround for an Oracle 9i bug witch is unable to convert from Short to NUMERIC but does understand SMALLINT
1202: oCol = new DBColumn(sName, sColName,
1203: (short) Types.SMALLINT, sTypeName,
1204: iPrecision, iDigits, iNullable, iColPos);
1205: } else {
1206: oCol = new DBColumn(sName, sColName, iSQLType,
1207: sTypeName, iPrecision, iDigits, iNullable,
1208: iColPos);
1209: }
1210:
1211: // Establecer el comportamiento de no tocar en ningún caso los campos dt_created
1212: // quitar este if si se desea asignarlos manualmente al insertar cada registro
1213: if (!sColName.equals(DB.dt_created))
1214: oColumns.add(oCol);
1215: } // next
1216:
1217: if (DebugFile.trace)
1218: DebugFile.writeln("ResultSet.close()");
1219:
1220: oRSet.close();
1221: oRSet = null;
1222: oStmt.close();
1223: oStmt = null;
1224:
1225: if (5 == iDBMS) /* Oracle */{
1226:
1227: /* getPrimaryKeys() not working properly on some Oracle versions,
1228: use non portable implementation instead. Sergio 12-01-2004.
1229:
1230: Code until v1.1.4:
1231:
1232: if (DebugFile.trace)
1233: DebugFile.writeln("DatabaseMetaData.getPrimaryKeys(null, " + sSchema.toUpperCase() + ", " + sName.toUpperCase() + ")");
1234:
1235: oRSet = oMData.getPrimaryKeys(sCatalog, sSchema.toUpperCase(), sName.toUpperCase());
1236: */
1237:
1238: oStmt = oConn.createStatement();
1239:
1240: if (DebugFile.trace) {
1241: if (null == sSchema)
1242: DebugFile
1243: .writeln("Statement.executeQuery(SELECT NULL AS TABLE_CAT, COLS.OWNER AS TABLE_SCHEM, COLS.TABLE_NAME, COLS.COLUMN_NAME, COLS.POSITION AS KEY_SEQ, COLS.CONSTRAINT_NAME AS PK_NAME FROM USER_CONS_COLUMNS COLS, USER_CONSTRAINTS CONS WHERE CONS.OWNER=COLS.OWNER AND CONS.CONSTRAINT_NAME=COLS.CONSTRAINT_NAME AND CONS.CONSTRAINT_TYPE='P' AND CONS.TABLE_NAME='"
1244: + sName.toUpperCase() + "')");
1245: else
1246: DebugFile
1247: .writeln("Statement.executeQuery(SELECT NULL AS TABLE_CAT, COLS.OWNER AS TABLE_SCHEM, COLS.TABLE_NAME, COLS.COLUMN_NAME, COLS.POSITION AS KEY_SEQ, COLS.CONSTRAINT_NAME AS PK_NAME FROM USER_CONS_COLUMNS COLS, USER_CONSTRAINTS CONS WHERE CONS.OWNER=COLS.OWNER AND CONS.CONSTRAINT_NAME=COLS.CONSTRAINT_NAME AND CONS.CONSTRAINT_TYPE='P' AND CONS.OWNER='"
1248: + sSchema.toUpperCase()
1249: + "' AND CONS.TABLE_NAME='"
1250: + sName.toUpperCase() + "')");
1251: }
1252:
1253: if (null == sSchema)
1254: oRSet = oStmt
1255: .executeQuery("SELECT NULL AS TABLE_CAT, COLS.OWNER AS TABLE_SCHEM, COLS.TABLE_NAME, COLS.COLUMN_NAME, COLS.POSITION AS KEY_SEQ, COLS.CONSTRAINT_NAME AS PK_NAME FROM USER_CONS_COLUMNS COLS, USER_CONSTRAINTS CONS WHERE CONS.OWNER=COLS.OWNER AND CONS.CONSTRAINT_NAME=COLS.CONSTRAINT_NAME AND CONS.CONSTRAINT_TYPE='P' AND CONS.TABLE_NAME='"
1256: + sName.toUpperCase() + "'");
1257: else
1258: oRSet = oStmt
1259: .executeQuery("SELECT NULL AS TABLE_CAT, COLS.OWNER AS TABLE_SCHEM, COLS.TABLE_NAME, COLS.COLUMN_NAME, COLS.POSITION AS KEY_SEQ, COLS.CONSTRAINT_NAME AS PK_NAME FROM USER_CONS_COLUMNS COLS, USER_CONSTRAINTS CONS WHERE CONS.OWNER=COLS.OWNER AND CONS.CONSTRAINT_NAME=COLS.CONSTRAINT_NAME AND CONS.CONSTRAINT_TYPE='P' AND CONS.OWNER='"
1260: + sSchema.toUpperCase()
1261: + "' AND CONS.TABLE_NAME='"
1262: + sName.toUpperCase() + "'");
1263:
1264: // End new code v1.2.0
1265: } else {
1266: if (DebugFile.trace)
1267: DebugFile
1268: .writeln("DatabaseMetaData.getPrimaryKeys("
1269: + sCatalog + "," + sSchema + ","
1270: + sName + ")");
1271:
1272: oRSet = oMData.getPrimaryKeys(sCatalog, sSchema, sName);
1273: }
1274:
1275: if (oRSet != null) {
1276: while (oRSet.next()) {
1277: oPrimaryKeys.add(oRSet.getString(4).toLowerCase());
1278: sSetPKCols += oRSet.getString(4) + "=? AND ";
1279: } // wend
1280:
1281: if (DebugFile.trace)
1282: DebugFile.writeln("pk cols " + sSetPKCols);
1283:
1284: if (sSetPKCols.length() > 7)
1285: sSetPKCols = sSetPKCols.substring(0, sSetPKCols
1286: .length() - 5);
1287:
1288: if (DebugFile.trace)
1289: DebugFile.writeln("ResultSet.close()");
1290:
1291: oRSet.close();
1292: oRSet = null;
1293: } // fi (oRSet)
1294:
1295: if (null != oStmt) {
1296: oStmt.close();
1297: oStmt = null;
1298: }
1299:
1300: oColIterator = oColumns.listIterator();
1301:
1302: while (oColIterator.hasNext()) {
1303: sCol = ((DBColumn) oColIterator.next()).getName();
1304:
1305: sGetAllCols += sCol + ",";
1306: sSetAllCols += "?,";
1307:
1308: if (!oPrimaryKeys.contains(sCol)
1309: && !sCol.equalsIgnoreCase(DB.dt_created))
1310: sSetNoPKCols += sCol + "=?,";
1311: } // wend
1312:
1313: if (DebugFile.trace)
1314: DebugFile.writeln("get all cols " + sGetAllCols);
1315:
1316: if (sGetAllCols.length() > 0)
1317: sGetAllCols = sGetAllCols.substring(0, sGetAllCols
1318: .length() - 1);
1319: else
1320: sGetAllCols = "*";
1321:
1322: if (DebugFile.trace)
1323: DebugFile.writeln("set all cols " + sSetAllCols);
1324:
1325: if (sSetAllCols.length() > 0)
1326: sSetAllCols = sSetAllCols.substring(0, sSetAllCols
1327: .length() - 1);
1328:
1329: if (DebugFile.trace)
1330: DebugFile.writeln("set no pk cols " + sSetNoPKCols);
1331:
1332: if (sSetNoPKCols.length() > 0)
1333: sSetNoPKCols = sSetNoPKCols.substring(0, sSetNoPKCols
1334: .length() - 1);
1335:
1336: if (DebugFile.trace)
1337: DebugFile.writeln("set pk cols " + sSetPKCols);
1338:
1339: if (sSetPKCols.length() > 0) {
1340: sSelect = "SELECT " + sGetAllCols + " FROM " + sName
1341: + " WHERE " + sSetPKCols;
1342: sInsert = "INSERT INTO " + sName + "(" + sGetAllCols
1343: + ") VALUES (" + sSetAllCols + ")";
1344: if (sSetNoPKCols.length() > 0)
1345: sUpdate = "UPDATE " + sName + " SET "
1346: + sSetNoPKCols + " WHERE " + sSetPKCols;
1347: else
1348: sUpdate = null;
1349: sDelete = "DELETE FROM " + sName + " WHERE "
1350: + sSetPKCols;
1351: sExists = "SELECT NULL FROM " + sName + " WHERE "
1352: + sSetPKCols;
1353: } else {
1354: sSelect = null;
1355: sInsert = "INSERT INTO " + sName + "(" + sGetAllCols
1356: + ") VALUES (" + sSetAllCols + ")";
1357: sUpdate = null;
1358: sDelete = null;
1359: sExists = null;
1360: }
1361: } // fi (o==iErrCode)
1362:
1363: if (DebugFile.trace) {
1364: DebugFile.writeln(sSelect != null ? sSelect
1365: : "NO SELECT STATEMENT");
1366: DebugFile.writeln(sInsert != null ? sInsert
1367: : "NO INSERT STATEMENT");
1368: DebugFile.writeln(sUpdate != null ? sUpdate
1369: : "NO UPDATE STATEMENT");
1370: DebugFile.writeln(sDelete != null ? sDelete
1371: : "NO DELETE STATEMENT");
1372: DebugFile.writeln(sExists != null ? sExists
1373: : "NO EXISTS STATEMENT");
1374:
1375: DebugFile.decIdent();
1376: DebugFile.writeln("End DBTable.readColumns()");
1377: }
1378:
1379: } // readColumns
1380:
1381: // ----------------------------------------------------------
1382:
1383: private String sCatalog;
1384: private String sSchema;
1385: private String sName;
1386: private int iHashCode;
1387: private LinkedList oColumns;
1388: private LinkedList oPrimaryKeys;
1389:
1390: private String sSelect;
1391: private String sInsert;
1392: private String sUpdate;
1393: private String sDelete;
1394: private String sExists;
1395:
1396: } // DBTable
|