Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 6E600200C68 for ; Wed, 19 Apr 2017 01:52:54 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 6CC3F160BB2; Tue, 18 Apr 2017 23:52:54 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 732DE160BAF for ; Wed, 19 Apr 2017 01:52:52 +0200 (CEST) Received: (qmail 76289 invoked by uid 500); 18 Apr 2017 23:52:51 -0000 Mailing-List: contact commits-help@trafodion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: commits@trafodion.apache.org Delivered-To: mailing list commits@trafodion.apache.org Received: (qmail 76251 invoked by uid 99); 18 Apr 2017 23:52:51 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Apr 2017 23:52:51 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id DF0E71A03DA for ; Tue, 18 Apr 2017 23:52:50 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.222 X-Spam-Level: X-Spam-Status: No, score=-4.222 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id TFcfhcuhF5mr for ; Tue, 18 Apr 2017 23:52:36 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 31A8F60E56 for ; Tue, 18 Apr 2017 23:52:23 +0000 (UTC) Received: (qmail 72460 invoked by uid 99); 18 Apr 2017 23:52:22 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Apr 2017 23:52:22 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 38258DFDAC; Tue, 18 Apr 2017 23:52:22 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dbirdsall@apache.org To: commits@trafodion.incubator.apache.org Date: Tue, 18 Apr 2017 23:52:57 -0000 Message-Id: <20ee79025faf4fffb2ab43eb79824166@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [37/44] incubator-trafodion git commit: Refact package name archived-at: Tue, 18 Apr 2017 23:52:54 -0000 http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/51a83dc2/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClob.java ---------------------------------------------------------------------- diff --git a/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClob.java b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClob.java new file mode 100644 index 0000000..1d9f03b --- /dev/null +++ b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClob.java @@ -0,0 +1,1017 @@ +// @@@ START COPYRIGHT @@@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +// +// @@@ END COPYRIGHT @@@ + +/* -*-java-*- + * Filename : SQLMXClob.java + * Description : This program implements the java.sql.Clob interface + * + */ + +package org.apache.trafodion.jdbc.t2; + +import java.sql.*; +import java.io.InputStream; +import java.io.Reader; +import java.io.OutputStream; +import java.io.Writer; +import java.io.IOException; +import java.util.Date; +import java.io.PrintWriter; + +public class SQLMXClob extends SQLMXLob implements Clob +{ + public InputStream getAsciiStream() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_getAsciiStream].methodEntry(); + try + { + checkIfCurrent(); + // Close the reader and inputStream hander over earlier + if (reader_ != null) + { + try + { + reader_.close(); + } + catch (IOException e) + { + } + finally + { + reader_ = null; + } + } + return getInputStream(); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getAsciiStream].methodExit(); + } + } + + public Reader getCharacterStream() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_getCharacterStream].methodEntry(); + try + { + checkIfCurrent(); + // Close the reader and inputStream hander over earlier + if (reader_ != null) + { + try + { + reader_.close(); + } + catch (IOException e) + { + } + finally + { + reader_ = null; + } + } + if (inputStream_ != null) + { + try + { + inputStream_.close(); + } + catch (IOException e) + { + } + finally + { + inputStream_ = null; + } + } + reader_ = new SQLMXClobReader(conn_, this); + return reader_; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getCharacterStream].methodExit(); + } + } + + public String getSubString(long pos, int length) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_getSubString].methodEntry(); + try + { + int startChunkNo; + int endChunkNo; + int offset; + int copyLen; + int dataLength; + long clobDataLen; + String data; + StringBuffer retString; + + if (pos <= 0 || length < 0 ) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = "Clob.getSubString(long, int): position is less than or equal to 0, or length is less than 0"; + throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); + } + + + // Clob data total length must be larger than pos supplied (used to offset the substring) +// clobDataLen = length(); +// if (pos > clobDataLen) +// { +// Object[] messageArguments = new Object[1]; +// messageArguments[0] = "Clob.getSubString(long, int): position (" + pos + ") exceeds the Clob data length (" + clobDataLen + ")"; +// throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); +// } + + + checkIfCurrent(); + startChunkNo = (int)((pos-1) / chunkSize_); + endChunkNo = (int)((pos-1+length)/ chunkSize_); + copyLen = length; + offset = (int)((pos-1) % chunkSize_); + retString = new StringBuffer(length); + + prepareGetLobDataStmt(); + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "getSubString(" + pos + "," + length + ") - GetLobDataStmt params: tableName_=" + tableName_ + + " dataLocator_=" + dataLocator_ + + " startChunkNo=" + startChunkNo + + " endChunkNo=" + endChunkNo); + } + + synchronized (conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT]) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setString(1, tableName_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setLong(2, dataLocator_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setInt(3, startChunkNo); + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setInt(4, endChunkNo); + ResultSet rs = conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].executeQuery(); + try + { + while (rs.next()) + { + data = rs.getString(1); + dataLength = data.length()-offset; + + if (dataLength >= copyLen) + { + retString.append(data.substring(offset, offset+copyLen)); + break; + } + else + { + if (offset == 0) + retString.append(data); + else + retString.append(data.substring(offset)); + copyLen -= dataLength; + } + offset = 0; // reset the offset + } + } + finally + { + rs.close(); + } + } + return retString.toString(); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getSubString].methodExit(); + } + } + + public long position(Clob searchstr, long start) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_position_LJ_clob].methodEntry(); + try + { + String searchString; + + if (start <= 0 ) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = "Clob.position(Clob, long)"; + throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); + } + checkIfCurrent(); + searchString = searchstr.getSubString(1L,(int)searchstr.length()); + return position(searchString, start); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_position_LJ_clob].methodExit(); + } + } + + public long position(String searchstr, long start) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_position_LJ_str].methodEntry(); + try + { + String clobData; + long retValue; + + if (start <= 0 ) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = "Clob.position(String, long)"; + throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); + } + checkIfCurrent(); + clobData = getSubString(start, (int)length()); + retValue = clobData.indexOf(searchstr); + if (retValue != -1) + retValue += start; + + return retValue; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_position_LJ_str].methodExit(); + } + } + + public OutputStream setAsciiStream(long pos) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_setAsciiStream].methodEntry(); + try + { + // Check if Autocommit is set, and no external transaction exists + checkAutoCommitExtTxn(); + checkIfCurrent(); + // Close the writer and OutputStream hander over earlier + if (writer_ != null) + { + try + { + writer_.close(); + } + catch (IOException e) + { + } + finally + { + writer_ = null; + } + } + return setOutputStream(pos); + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_setAsciiStream].methodExit(); + } + } + + public Writer setCharacterStream(long pos) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_setCharacterStream].methodEntry(); + try + { + // Check if Autocommit is set, and no external transaction exists + checkAutoCommitExtTxn(); + checkIfCurrent(); + // Close the writer and OutputStream hander over earlier + if (writer_ != null) + { + try + { + writer_.close(); + } + catch (IOException e) + { + } + finally + { + writer_ = null; + } + } + if (outputStream_ != null) + { + try + { + outputStream_.close(); + } + catch (IOException e) + { + } + finally + { + outputStream_ = null; + } + } + writer_ = new SQLMXClobWriter(conn_, this, pos); + return writer_; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_setCharacterStream].methodExit(); + } + } + + public int setString(long pos, String str) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_setString_JL].methodEntry(); + try + { + if (str == null) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = "Clob.setString(long, String)"; + throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); + } + return setString(pos, str, 0, str.length()); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_setString_JL].methodExit(); + } + } + + public int setString(long pos, String str, int offset, int len) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_setString_JLII].methodEntry(); + try + { + int endChunkNo; + int updOffset; + int updLen; + int chunkNo; + long lobLenForUpd; + int strOffset; + int retLen; + int totalRetLen; + int copyLen; + long remLen; + long lobLen; + + if (str == null || pos <= 0 || len < 0 || offset < 0) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = "Clob.setString(long, String, int, int)"; + throw Messages.createSQLException(conn_.locale_,"invalid_input_value", messageArguments); + } + checkIfCurrent(); + lobLen = length(); + if (pos > lobLen+1) + throw Messages.createSQLException(conn_.locale_,"invalid_position_value", null); + copyLen = len; + remLen = pos-1+len; // Length that needs to be either updated or inserted + strOffset = offset; + totalRetLen = 0; + chunkNo = (int)((pos-1)/ chunkSize_); // Starting chunkNo + + // Calculate the length that can be updated rounded to chunk size + if ((lobLen % chunkSize_) == 0) + lobLenForUpd = (lobLen / chunkSize_) * chunkSize_; + else + lobLenForUpd = ((lobLen / chunkSize_)+1) * chunkSize_; // LOB data offset to the first char of the NEXT chunk insertion + + if (remLen <= lobLenForUpd) + updLen = len; + else + updLen = (int)(lobLenForUpd - (pos-1)); + + if (updLen > 0) + { + updOffset = (int)((pos-1) % chunkSize_); // offset from the beginning of the chunk + prepareUpdLobDataStmt(); + + synchronized (conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT]) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setString(4, tableName_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setLong(5, dataLocator_); + + while (true) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setInt(6, chunkNo); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setInt(1, updOffset); + if ((updOffset + updLen) <= chunkSize_) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setInt(3, updOffset + updLen + 1); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setString(2, str.substring(strOffset, strOffset+updLen)); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].executeUpdate(); + totalRetLen += updLen; + strOffset += updLen; + chunkNo++; + break; + } + else + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setInt(3, chunkSize_+1); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].setString(2, str.substring(strOffset, strOffset+chunkSize_-updOffset)); + conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT].executeUpdate(); + totalRetLen += (chunkSize_-updOffset); + strOffset += (chunkSize_-updOffset); + updLen -= (chunkSize_-updOffset); + chunkNo++; + } + updOffset = 0; + } + } + copyLen = (int)(remLen - lobLenForUpd); + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "setString(" + pos + ",," + offset + "," + len + + ") - UpdLobDataStmt params: tableName_=" + tableName_ + + " dataLocator_=" + dataLocator_ + " chunkNo=" + chunkNo + + " updOffset=" + updOffset + " updLen=" + updLen + + " remLen=" + remLen + " lobLenForUpd=" + lobLenForUpd + + " strOffset=" + strOffset + " totalRetLen=" + totalRetLen); + } + } + if (remLen > lobLenForUpd) + { + while (true) + { + prepareInsLobDataStmt(); + + synchronized (conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT]) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setString(1, tableName_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setLong(2, dataLocator_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setInt(3, chunkNo); + if (copyLen <= chunkSize_) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setString(4, str.substring(strOffset, strOffset+copyLen)); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].executeUpdate(); + strOffset += copyLen; + totalRetLen += copyLen; + break; + } + else + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setString(4, str.substring(strOffset, strOffset+chunkSize_)); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].executeUpdate(); + strOffset += chunkSize_; + copyLen -= chunkSize_; + totalRetLen += chunkSize_; + } + chunkNo++; + } + } + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "setString(" + pos + ",," + offset + "," + len + + ") - InsLobDataStmt params: tableName_=" + tableName_ + + " dataLocator_=" + dataLocator_ + " (total)chunkNo=" + chunkNo + + " copyLen=" + copyLen + " strOffset=" + strOffset + + " totalRetLen=" + totalRetLen); + } + } + return totalRetLen; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_setString_JLII].methodExit(); + } + } + + void close() + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodEntry(); + try + { + try + { + if (reader_ != null) + reader_.close(); + if (writer_ != null) + writer_.close(); + } + catch (IOException e) + { + } + finally + { + reader_ = null; + writer_ = null; + } + super.close(); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodExit(); + } + } + + // This function populates the Clob data from one of the following: + // 1. InputStream set in PreparedStatement.setAsciiStream + // 2. Reader set in PreparedStatement.setCharacterStream + // 3. From another clob set in PreparedStatement.setClob or ResultSet.updateClob + // This function is called at the time of PreparedStatement.executeUpdate, execute and + // executeBatch + + void populate() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_populate].methodEntry(); + try + { + SQLMXLobOutputStream os; + SQLMXClobWriter cw; + + if (is_ != null) + { + os = (SQLMXLobOutputStream)setOutputStream(1); + os.populate(is_, isLength_); + is_ = null; + } + else if (ir_ != null) + { + cw = (SQLMXClobWriter)setCharacterStream(1); + cw.populate(ir_, irLength_); + ir_ = null; + } + else if (inputLob_ != null) + { + populateFromClob(); + inputLob_ = null; + } + else if (inputLobStr_ != null) + { + setString(1, inputLobStr_); + inputLobStr_ = null; + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_populate].methodExit(); + } + } + + void populateFromClob() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_populateFromClob].methodEntry(); + try + { + long pos; + String s; + int ret; + ResultSet rs; + SQLMXClob inputClob; + int chunkNo = 0; + + pos = 1; + if (inputLob_ instanceof SQLMXClob) + { + // When SQL/MX supports insert into a table by selecting some other rows in + // the same table, we should change the code to do so + // Until then, we read a row and write to the same table with different + // data locator till all the rows are read + inputClob = (SQLMXClob)inputLob_; + + prepareGetLobDataStmt(); + prepareInsLobDataStmt(); + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "populateFromClob() - GetLobDataStmt params: tableName_=" + inputClob.tableName_ + + " dataLocator_=" + inputClob.dataLocator_ + " chunkNo=0" + + " Integer.MAX_VALUE=" + Integer.MAX_VALUE); + } + + synchronized (conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT]) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setString(1, inputClob.tableName_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setLong(2, inputClob.dataLocator_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setInt(3, 0); // start ChunkNo + conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].setInt(4, Integer.MAX_VALUE); + rs = conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT].executeQuery(); + try + { + synchronized(conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT]) + { + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setString(1, tableName_); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setLong(2, dataLocator_); + + while (rs.next()) + { + s = rs.getString(1); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setInt(3, chunkNo); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].setString(4, s); + conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT].executeUpdate(); + chunkNo++; + } + } + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "populateFromClob() - InsLobDataStmt params: tableName_=" + tableName_ + + " dataLocator_=" + dataLocator_ + " (total)chunkNo=" + chunkNo); + } + } + finally + { + rs.close(); + } + } + } + else + { + while (true) + { + s = inputLob_.getSubString(pos, chunkSize_); + if (s.length() == 0) + break; + ret = setString(pos, s); + pos += s.length(); + } + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_populateFromClob].methodExit(); + } + } + + // The following methods are used to prepare the LOB statement specific + // to CLOB objects, and re-prepares if the lobTableName_ has changed. + void prepareGetLobLenStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareGetLobLenStmt].methodEntry(); + try + { + conn_.prepareGetLobLenStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareGetLobLenStmt].methodExit(); + } + } + + void prepareDelLobDataStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareDelLobDataStmt].methodEntry(); + try + { + conn_.prepareDelLobDataStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareDelLobDataStmt].methodExit(); + } + } + + void prepareGetLobDataStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareGetLobDataStmt].methodEntry(); + try + { + conn_.prepareGetLobDataStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareGetLobDataStmt].methodExit(); + } + } + + void prepareUpdLobDataStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareUpdLobDataStmt].methodEntry(); + try + { + conn_.prepareUpdLobDataStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareUpdLobDataStmt].methodExit(); + } + } + + void prepareInsLobDataStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareInsLobDataStmt].methodEntry(); + try + { + conn_.prepareInsLobDataStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareInsLobDataStmt].methodExit(); + } + } + + void prepareTrunLobDataStmt() throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareTrunLobDataStmt].methodEntry(); + try + { + conn_.prepareTrunLobDataStmt(lobTableName_,false); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_prepareTrunLobDataStmt].methodExit(); + } + } + + // The following methods are used to return the CLOB prepared statement + // from the connection object PS array for population and execution. + PreparedStatement getGetLobLenStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getGetLobLenStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_LEN_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getGetLobLenStmt].methodExit(); + } + } + + PreparedStatement getDelLobDataStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getDelLobDataStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_DEL_LOB_DATA_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getDelLobDataStmt].methodExit(); + } + } + + PreparedStatement getTrunLobDataStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getTrunLobDataStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_TRUN_LOB_DATA_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getTrunLobDataStmt].methodExit(); + } + } + + PreparedStatement getInsLobDataStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getInsLobDataStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_INS_LOB_DATA_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getInsLobDataStmt].methodExit(); + } + } + + PreparedStatement getUpdLobDataStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getUpdLobDataStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_UPD_LOB_DATA_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getUpdLobDataStmt].methodExit(); + } + } + + PreparedStatement getGetLobDataStmt() + { + if (JdbcDebugCfg.entryActive) debug[methodId_getGetLobDataStmt].methodEntry(); + try + { + return conn_.LobPrepStmts[SQLMXConnection.CLOB_GET_LOB_DATA_STMT]; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_getGetLobDataStmt].methodExit(); + } + } + + // Constructors + SQLMXClob(SQLMXConnection connection, String tableName, long dataLocator) throws SQLException + { + super(connection, tableName, dataLocator, connection.clobTableName_, false); + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJ].methodEntry(); + try + { + if (connection.clobTableName_ == null) + throw Messages.createSQLException(conn_.locale_,"no_clobTableName", null); + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJ].methodExit(); + } + } + + SQLMXClob(SQLMXConnection connection, String tableName, long dataLocator, InputStream x, + int length) throws SQLException + { + super(connection, tableName, dataLocator, x, length, connection.clobTableName_, false); + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJLI_stream].methodEntry(); + try + { + if (connection.clobTableName_ == null) + throw Messages.createSQLException(conn_.locale_,"no_clobTableName", null); + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJLI_stream].methodExit(); + } + } + + SQLMXClob(SQLMXConnection connection, String tableName, long dataLocator, Reader x, + int length) throws SQLException + { + super(connection, tableName, dataLocator, connection.clobTableName_, false); + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJLI_reader].methodEntry(); + try + { + if (connection.clobTableName_ == null) + throw Messages.createSQLException(conn_.locale_,"no_clobTableName", null); + ir_ = x; + irLength_ = length; + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJLI_reader].methodExit(); + } + } + + SQLMXClob(SQLMXConnection connection, String tableName, long dataLocator, Clob inputLob) throws SQLException + { + super(connection, tableName, dataLocator, connection.clobTableName_, false); + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJL_clob].methodEntry(); + try + { + if (connection.clobTableName_ == null) + throw Messages.createSQLException(conn_.locale_,"no_clobTableName", null); + inputLob_ = inputLob; + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJL_clob].methodExit(); + } + } + + SQLMXClob(SQLMXConnection connection, String tableName, long dataLocator, String lobStr) throws SQLException + { + super(connection, tableName, dataLocator, connection.clobTableName_, false); + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJL_string].methodEntry(); + try + { + if (connection.clobTableName_ == null) + throw Messages.createSQLException(conn_.locale_,"no_clobTableName", null); + inputLobStr_ = lobStr; + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClob_LLJL_string].methodExit(); + } + } + public void setTraceId(String traceId_) { + this.traceId_ = traceId_; + } + + public String getTraceId() { + traceWriter_ = SQLMXDataSource.traceWriter_; + + // Build up template portion of jdbcTrace output. Pre-appended to jdbcTrace entries. + // jdbcTrace:[XXXX]:[Thread[X,X,X]]:[XXXXXXXX]:ClassName. + if (traceWriter_ != null) + { + traceFlag_ = T2Driver.traceFlag_; + String className = getClass().getName(); + setTraceId(T2Driver.traceText + T2Driver.dateFormat.format(new Date()) + + "]:[" + Thread.currentThread() + "]:[" + hashCode() + "]:" + + className.substring(T2Driver.REMOVE_PKG_NAME,className.length()) + + "."); + } + return traceId_; + } + + //fields + private String traceId_; + static PrintWriter traceWriter_; + static int traceFlag_; + SQLMXClobReader reader_; + SQLMXClobWriter writer_; + Reader ir_; + int irLength_; + Clob inputLob_; + String inputLobStr_; + private static int methodId_getAsciiStream = 0; + private static int methodId_getCharacterStream = 1; + private static int methodId_getSubString = 2; + private static int methodId_position_LJ_clob = 3; + private static int methodId_position_LJ_str = 4; + private static int methodId_setAsciiStream = 5; + private static int methodId_setCharacterStream = 6; + private static int methodId_setString_JL = 7; + private static int methodId_setString_JLII = 8; + private static int methodId_close = 9; + private static int methodId_populate = 10; + private static int methodId_populateFromClob = 11; + private static int methodId_SQLMXClob_LLJ = 12; + private static int methodId_SQLMXClob_LLJLI_stream = 13; + private static int methodId_SQLMXClob_LLJLI_reader = 14; + private static int methodId_SQLMXClob_LLJL_clob = 15; + private static int methodId_SQLMXClob_LLJL_string = 16; + private static int methodId_prepareGetLobLenStmt = 17; + private static int methodId_prepareDelLobDataStmt = 18; + private static int methodId_prepareGetLobDataStmt = 19; + private static int methodId_prepareUpdLobDataStmt = 20; + private static int methodId_prepareInsLobDataStmt = 21; + private static int methodId_prepareTrunLobDataStmt = 22; + private static int methodId_getGetLobLenStmt = 23; + private static int methodId_getDelLobDataStmt = 24; + private static int methodId_getTrunLobDataStmt = 25; + private static int methodId_getInsLobDataStmt = 26; + private static int methodId_getUpdLobDataStmt = 27; + private static int methodId_getGetLobDataStmt = 28; + private static int totalMethodIds = 29; + private static JdbcDebug[] debug; + + static + { + String className = "SQLMXClob"; + if (JdbcDebugCfg.entryActive) + { + debug = new JdbcDebug[totalMethodIds]; + debug[methodId_getAsciiStream] = new JdbcDebug(className,"getAsciiStream"); + debug[methodId_getCharacterStream] = new JdbcDebug(className,"getCharacterStream"); + debug[methodId_getSubString] = new JdbcDebug(className,"getSubString"); + debug[methodId_position_LJ_clob] = new JdbcDebug(className,"position[LJ_clob]"); + debug[methodId_position_LJ_str] = new JdbcDebug(className,"position[LJ_str]"); + debug[methodId_setAsciiStream] = new JdbcDebug(className,"setAsciiStream"); + debug[methodId_setCharacterStream] = new JdbcDebug(className,"setCharacterStream"); + debug[methodId_setString_JL] = new JdbcDebug(className,"setString[JL]"); + debug[methodId_setString_JLII] = new JdbcDebug(className,"setString[JLII]"); + debug[methodId_close] = new JdbcDebug(className,"close"); + debug[methodId_populate] = new JdbcDebug(className,"populate"); + debug[methodId_populateFromClob] = new JdbcDebug(className,"populateFromClob"); + debug[methodId_SQLMXClob_LLJ] = new JdbcDebug(className,"SQLMXClob[LLJ]"); + debug[methodId_SQLMXClob_LLJLI_stream] = new JdbcDebug(className,"SQLMXClob[LLJLI_stream]"); + debug[methodId_SQLMXClob_LLJLI_reader] = new JdbcDebug(className,"SQLMXClob[LLJLI_reader]"); + debug[methodId_SQLMXClob_LLJL_clob] = new JdbcDebug(className,"SQLMXClob[LLJL_clob]"); + debug[methodId_SQLMXClob_LLJL_string] = new JdbcDebug(className,"SQLMXClob[LLJL_string]"); + debug[methodId_prepareGetLobLenStmt] = new JdbcDebug(className,"prepareGetLobLenStmt"); + debug[methodId_prepareDelLobDataStmt] = new JdbcDebug(className,"prepareDelLobDataStmt"); + debug[methodId_prepareGetLobDataStmt] = new JdbcDebug(className,"prepareGetLobDataStmt"); + debug[methodId_prepareUpdLobDataStmt] = new JdbcDebug(className,"prepareUpdLobDataStmt"); + debug[methodId_prepareInsLobDataStmt] = new JdbcDebug(className,"prepareInsLobDataStmt"); + debug[methodId_prepareTrunLobDataStmt] = new JdbcDebug(className,"prepareTrunLobDataStmt"); + debug[methodId_getGetLobLenStmt] = new JdbcDebug(className,"getGetLobLenStmt"); + debug[methodId_getDelLobDataStmt] = new JdbcDebug(className,"getDelLobDataStmt"); + debug[methodId_getTrunLobDataStmt] = new JdbcDebug(className,"getTrunLobDataStmt"); + debug[methodId_getInsLobDataStmt] = new JdbcDebug(className,"getInsLobDataStmt"); + debug[methodId_getUpdLobDataStmt] = new JdbcDebug(className,"getUpdLobDataStmt"); + debug[methodId_getGetLobDataStmt] = new JdbcDebug(className,"getGetLobDataStmt"); + } + } + public void free() throws SQLException { + // TODO Auto-generated method stub + + } + + public Reader getCharacterStream(long pos, long length) throws SQLException { + // TODO Auto-generated method stub + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/51a83dc2/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobReader.java ---------------------------------------------------------------------- diff --git a/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobReader.java b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobReader.java new file mode 100644 index 0000000..9d2e46d --- /dev/null +++ b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobReader.java @@ -0,0 +1,481 @@ +// @@@ START COPYRIGHT @@@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +// +// @@@ END COPYRIGHT @@@ + +/* -*-java-*- + * Filename : SQLMXClobReader.java + * Description : This program implements the Reader interface. This object + * returned to the application when Clob.getAsciiStream() + * method is called. The application can use this object + * to read the clob data + */ + +package org.apache.trafodion.jdbc.t2; + +import java.sql.*; +import java.io.Reader; +import java.io.IOException; +import java.util.Date; +import java.io.PrintWriter; + +public class SQLMXClobReader extends Reader +{ + + public void close() throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodEntry(); + try + { + isClosed_ = true; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodExit(); + } + } + + public void mark(int readAheadLimit) throws IOException + { + if (JdbcDebugCfg.entryActive) + { + debug[methodId_mark].methodEntry(); + debug[methodId_mark].methodExit(); + } + } + + public boolean markSupported() + { + if (JdbcDebugCfg.entryActive) debug[methodId_markSupported].methodEntry(); + try + { + return false; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_markSupported].methodExit(); + } + } + + public int read() throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_V].methodEntry(); + try + { + int retValue = 0; + + if (isClosed_) + throw new IOException("Reader is in closed state"); + if (currentChar_ == charsRead_) + retValue = readChunkThrowIO(null, 0, clob_.chunkSize_); + if (retValue != -1) + { + retValue = chunk_[currentChar_]; + if (currentChar_ != charsRead_) + currentChar_++; + } + return retValue; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_V].methodExit(); + } + } + + public int read(char[] cbuf) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_C].methodEntry(); + try + { + if (cbuf == null) + throw new IOException("Invalid input value"); + return read(cbuf, 0, cbuf.length); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_C].methodExit(); + } + } + + public int read(char[] cbuf, + int off, + int len) + throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_CII].methodEntry(); + try + { + int readLen; + int copyLen; + int copyOffset; + int tempLen = 0; + int rowsToRead; + int retLen; + + if (isClosed_) + throw new IOException("Reader is in closed state"); + if (cbuf == null) + throw new IOException("Invalid input value"); + copyLen = len; + copyOffset = off; + readLen = 0; + if (currentChar_ < charsRead_) + { + if (copyLen+currentChar_ <= charsRead_) + { + System.arraycopy(chunk_, currentChar_, cbuf, copyOffset, copyLen); + currentChar_ += copyLen; + readLen = copyLen; + return readLen; + } + else + { + tempLen = charsRead_- currentChar_; + System.arraycopy(chunk_, currentChar_, cbuf, copyOffset, tempLen); + copyOffset += tempLen; + copyLen -= tempLen; + currentChar_ += tempLen; + } + } + readLen = readChunkThrowIO(cbuf, copyOffset, copyLen); + if (readLen != -1) + retLen = readLen + tempLen; + else + retLen = tempLen; + if (retLen == 0) + return -1; + else + return retLen; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_read_CII].methodExit(); + } + } + + public void reset() + throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_reset].methodEntry(); + try + { + if (isClosed_) + throw new IOException("Reader is in closed state"); + currentChar_ = 0; + currentChunkNo_ = 0; + charsRead_ = 0; + return; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_reset].methodExit(); + } + } + + public long skip(long n) + throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_skip].methodEntry(); + try + { + long charsToSkip; + int noOfChunks = 0; + int remChars; + long retLen = 0; + long charsSkipped = 0; + int oldChunkNo; + int readLen; + + if (isClosed_) + throw new IOException("Reader is in closed state"); + if (n <= 0) + return 0; + if (currentChar_ + n > charsRead_) + { + charsSkipped = charsRead_ - currentChar_; + charsToSkip = n - charsSkipped; + currentChar_ += charsSkipped; + } + else + { + currentChar_ += n; + return n; + } + noOfChunks += (int)((charsToSkip-1) / clob_.chunkSize_); + if ((charsToSkip % clob_.chunkSize_) == 0) + remChars = clob_.chunkSize_; + else + remChars = (int)(charsToSkip % clob_.chunkSize_); + oldChunkNo = currentChunkNo_; // Which is already 1 more + currentChunkNo_ = currentChunkNo_ + noOfChunks; + retLen = readChunkThrowIO(null, 0, clob_.chunkSize_); + if (retLen != -1) + { + charsSkipped += (currentChunkNo_ - oldChunkNo -1) * clob_.chunkSize_; + if (retLen < remChars) + remChars= (int)retLen; + currentChar_ = remChars; + charsSkipped += remChars; + } + else + { + if (currentChunkNo_ > 0) + readLen = ((currentChunkNo_-1) * clob_.chunkSize_) + currentChar_; + else + readLen = currentChar_; + try + { + charsSkipped = charsSkipped + clob_.length() - readLen; + } + catch (SQLException e) + { + throw new IOException(SQLMXLob.convSQLExceptionToIO(e)); + } + // Exclude the bytes that are in chunk already + remChars = (int)(charsSkipped - (charsRead_ - currentChar_)); + noOfChunks += (int)((remChars-1) / clob_.chunkSize_); + currentChunkNo_ = oldChunkNo + noOfChunks; + //calculate the bytes in the chunk and set currentChar and charsRead + //to reach EOD + if (remChars == 0) + { + currentChar_ = 0; + charsRead_ = 0; + } + else + { + if ((remChars % clob_.chunkSize_) == 0) + currentChar_ = clob_.chunkSize_; + else + currentChar_ = (int)(remChars % clob_.chunkSize_); + charsRead_ = currentChar_; + } + } + return charsSkipped; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_skip].methodExit(); + } + } + + int readChunkThrowIO(char[] c, int off, int len) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_readChunkThrowIO].methodEntry(); + try + { + int readLen; + + try + { + readLen = readChunk(c, off, len); + } + catch (SQLException e) + { + throw new IOException(SQLMXLob.convSQLExceptionToIO(e)); + } + return readLen; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_readChunkThrowIO].methodExit(); + } + } + + int readChunk(char[] c, int off, int len) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_readChunk].methodEntry(); + try + { + int rowsToRead; + String data; + int copyLen; + int copyOffset; + int readLen = 0; + int dataLen; + + rowsToRead = (len-1)/clob_.chunkSize_; + clob_.prepareGetLobDataStmt(); + PreparedStatement GetClobDataStmt = clob_.getGetLobDataStmt(); + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "readChunk(," + off + "," + len + ") - GetLobDataStmt params: tableName_=" + clob_.tableName_ + + " dataLocator_=" + clob_.dataLocator_ + + " currentChunkNo_=" + currentChunkNo_ + + " currentChunkNo_+rowsToRead=" + (currentChunkNo_+rowsToRead)); + } + + synchronized (GetClobDataStmt) + { + GetClobDataStmt.setString(1, clob_.tableName_); + GetClobDataStmt.setLong(2, clob_.dataLocator_); + GetClobDataStmt.setInt(3, currentChunkNo_); + GetClobDataStmt.setInt(4, currentChunkNo_+rowsToRead); + ResultSet rs = GetClobDataStmt.executeQuery(); + copyLen = len; + copyOffset = off; + try + { + while (rs.next()) + { + data = rs.getString(1); + currentChunkNo_++; + charsRead_ = data.length(); + dataLen = charsRead_; + if (c == null) + { + data.getChars(0, dataLen, chunk_, 0); + readLen += dataLen; + currentChar_ = 0; + break; + } + else + { + if (copyLen >= dataLen) + { + data.getChars(0, dataLen, c, copyOffset); + copyLen -= dataLen; + readLen += dataLen; + copyOffset += dataLen; + currentChar_ = dataLen; + } + else + { + data.getChars(0, copyLen, c, copyOffset); + // copy the rest of data to chunk + data.getChars(copyLen, dataLen, chunk_, copyLen); + readLen += copyLen; + currentChar_ = copyLen; + break; + } + } + } + } + finally + { + rs.close(); + } + } + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + traceWriter_.println(getTraceId() + + "readChunk(," + off + "," + len + ") - LOB data read: charsRead_=" + charsRead_ + + " readLen=" + readLen + " copyLen=" + copyLen + " currentChunkNo_=" + currentChunkNo_); + } + + if (readLen == 0) + return -1; + else + return readLen; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_readChunk].methodExit(); + } + } + + // constructors + SQLMXClobReader(SQLMXConnection connection, SQLMXClob clob) + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClobReader].methodEntry(); + try + { + clob_ = clob; + conn_ = connection; + chunk_ = new char[clob_.chunkSize_]; + + traceWriter_ = SQLMXDataSource.traceWriter_; + + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClobReader].methodExit(); + } + } + public void setTraceId(String traceId_) { + this.traceId_ = traceId_; + } + + public String getTraceId() { + // Build up template portion of jdbcTrace output. Pre-appended to jdbcTrace entries. + // jdbcTrace:[XXXX]:[Thread[X,X,X]]:[XXXXXXXX]:ClassName. + if (traceWriter_ != null) + { + traceFlag_ = T2Driver.traceFlag_; + String className = getClass().getName(); + setTraceId(T2Driver.traceText + T2Driver.dateFormat.format(new Date()) + + "]:[" + Thread.currentThread() + "]:[" + hashCode() + "]:" + + className.substring(T2Driver.REMOVE_PKG_NAME,className.length()) + + "."); + } + return traceId_; + } + + // Fields + private String traceId_; + static PrintWriter traceWriter_; + static int traceFlag_; + SQLMXClob clob_; + SQLMXConnection conn_; + boolean isClosed_; + char[] chunk_; + int currentChar_; + int currentChunkNo_; + int charsRead_; + + private static int methodId_close = 0; + private static int methodId_mark = 1; + private static int methodId_markSupported = 2; + private static int methodId_read_V = 3; + private static int methodId_read_C = 4; + private static int methodId_read_CII = 5; + private static int methodId_reset = 6; + private static int methodId_skip = 7; + private static int methodId_readChunkThrowIO = 8; + private static int methodId_readChunk = 9; + private static int methodId_SQLMXClobReader = 10; + private static int totalMethodIds = 11; + private static JdbcDebug[] debug; + + static + { + String className = "SQLMXClobReader"; + if (JdbcDebugCfg.entryActive) + { + debug = new JdbcDebug[totalMethodIds]; + debug[methodId_close] = new JdbcDebug(className,"close"); + debug[methodId_mark] = new JdbcDebug(className,"mark"); + debug[methodId_markSupported] = new JdbcDebug(className,"markSupported"); + debug[methodId_read_V] = new JdbcDebug(className,"read[V]"); + debug[methodId_read_C] = new JdbcDebug(className,"read[C]"); + debug[methodId_read_CII] = new JdbcDebug(className,"read[CII]"); + debug[methodId_reset] = new JdbcDebug(className,"reset"); + debug[methodId_skip] = new JdbcDebug(className,"skip"); + debug[methodId_readChunkThrowIO] = new JdbcDebug(className,"readChunkThrowIO"); + debug[methodId_readChunk] = new JdbcDebug(className,"readChunk"); + debug[methodId_SQLMXClobReader] = new JdbcDebug(className,"SQLMXClobReader"); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-trafodion/blob/51a83dc2/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobWriter.java ---------------------------------------------------------------------- diff --git a/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobWriter.java b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobWriter.java new file mode 100644 index 0000000..a489c3e --- /dev/null +++ b/core/conn/jdbc_type2/src/main/java/org/apache/trafodion/jdbc/t2/SQLMXClobWriter.java @@ -0,0 +1,486 @@ +// @@@ START COPYRIGHT @@@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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. +// +// @@@ END COPYRIGHT @@@ + +/* -*-java-*- + * Filename : SQLMXClobWriter.java + * Description : This program implements the Writer interface. This + * object returned to the application when Clob.setAsciiStream() + * method is called. The application can use this object to write + * the clob data + */ + +package org.apache.trafodion.jdbc.t2; + +import java.sql.*; +import java.io.Writer; +import java.io.Reader; +import java.io.IOException; +import java.util.Date; +import java.io.PrintWriter; + +public class SQLMXClobWriter extends Writer +{ + public void close() throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodEntry(); + try + { + if (! isClosed_) + { + flush(); + isClosed_ = true; + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_close].methodExit(); + } + } + + public void flush() throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_flush].methodEntry(); + try + { + if (isClosed_) + throw new IOException("Output stream is in closed state"); + if (! isFlushed_) + { + writeChunkThrowIO(null); + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_flush].methodExit(); + } + } + + public void write(char[] cbuf) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_C].methodEntry(); + try + { + if (cbuf == null) + throw new IOException("Invalid input value"); + write(cbuf, 0, cbuf.length); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_C].methodExit(); + } + } + + public void write(char[] cbuf, int off, int len) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_CII].methodEntry(); + try + { + int copyLen; + int srcOffset; + int tempLen; + + if (isClosed_) + throw new IOException("Writer is in closed state"); + if (cbuf == null) + throw new IOException("Invalid input value"); + if (off < 0 || len < 0 || off > cbuf.length) + throw new IndexOutOfBoundsException( + "length or offset is less than 0 or offset is greater than the length of array"); + srcOffset = off; + copyLen = len; + while (true) + { + if (copyLen+currentChar_ < (clob_.chunkSize_)) + { + System.arraycopy(cbuf, srcOffset, chunk_, currentChar_, copyLen); + currentChar_ += copyLen; + isFlushed_ = false; + break; + } + else + { + if (currentChar_ != 0) + { + tempLen = clob_.chunkSize_-currentChar_; + System.arraycopy(cbuf, srcOffset, chunk_, currentChar_, tempLen); + currentChar_ += tempLen; + writeChunkThrowIO(null); + } + else + { + tempLen = clob_.chunkSize_; + currentChar_ += tempLen; + writeChunkThrowIO(new String(cbuf, srcOffset, tempLen)); + } + copyLen -= tempLen; + srcOffset += tempLen; + currentChar_ = 0; + } + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_CII].methodExit(); + } + } + + public void write(int c) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_I].methodEntry(); + try + { + if (isClosed_) + throw new IOException("Writer is in closed state"); + chunk_[currentChar_] = (char)c; + isFlushed_ = false; + currentChar_++; + if (currentChar_ == clob_.chunkSize_) + writeChunkThrowIO(null); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_I].methodExit(); + } + } + + public void write(String str) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_L].methodEntry(); + try + { + if (str == null) + throw new IOException("Invalid input value"); + write(str, 0, str.length()); + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_L].methodExit(); + } + } + + public void write(String str, int off, int len) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_LII].methodEntry(); + try + { + int tempLen; + int writeLen; + int srcOff; + + writeLen = len; + srcOff = off; + + if (isClosed_) + throw new IOException("Writer is in closed state"); + if (str == null) + throw new IOException("Invalid input value"); + if (currentChar_ != 0) + { + tempLen = clob_.chunkSize_ - currentChar_; + if (writeLen > tempLen) + { + char[] cbuf = new char[tempLen]; + str.getChars(srcOff, srcOff+tempLen, cbuf, 0); + write(cbuf, 0, cbuf.length); + writeLen -= tempLen; + srcOff += tempLen; + } + } + while (writeLen > 0) + { + if (writeLen < clob_.chunkSize_) + break; + else + { + writeChunkThrowIO(str.substring(srcOff, srcOff+clob_.chunkSize_)); + writeLen -= clob_.chunkSize_; + srcOff += clob_.chunkSize_; + } + } + if (writeLen != 0) + { + char[] cbuf = new char[writeLen]; + str.getChars(srcOff, srcOff+writeLen, cbuf, 0); + write(cbuf, 0, cbuf.length); + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_write_LII].methodExit(); + } + } + + void writeChunk(String str) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_writeChunk].methodEntry(); + try + { + String tempStr; + + if (currentChunkNo_ > updChunkNo_) + { + clob_.prepareInsLobDataStmt(); + PreparedStatement InsClobDataStmt = clob_.getInsLobDataStmt(); + + synchronized (InsClobDataStmt) + { + InsClobDataStmt.setString(1, clob_.tableName_); + InsClobDataStmt.setLong(2, clob_.dataLocator_); + InsClobDataStmt.setInt(3, currentChunkNo_); + if (str == null) + { + if (currentChar_ != clob_.chunkSize_) + tempStr = new String(chunk_, 0, currentChar_); + else + tempStr = new String(chunk_); + } + else + tempStr = str; + InsClobDataStmt.setString(4, tempStr); + InsClobDataStmt.executeUpdate(); + currentChunkNo_++; + currentChar_ = 0; + } + } + else + { + clob_.prepareUpdLobDataStmt(); + PreparedStatement UpdClobDataStmt = clob_.getUpdLobDataStmt(); + + synchronized (UpdClobDataStmt) + { + UpdClobDataStmt.setString(4, clob_.tableName_); + UpdClobDataStmt.setLong(5, clob_.dataLocator_); + UpdClobDataStmt.setInt(6, currentChunkNo_); + UpdClobDataStmt.setInt(1, updOffset_); + if (str == null) + { + if (updOffset_ != 0 || currentChar_ != clob_.chunkSize_) + tempStr = new String(chunk_, updOffset_, currentChar_-updOffset_); + else + tempStr = new String(chunk_); + } + else + tempStr = str; + UpdClobDataStmt.setInt(3, currentChar_+1); + UpdClobDataStmt.setString(2, tempStr); + UpdClobDataStmt.executeUpdate(); + currentChunkNo_++; + currentChar_ = 0; + updOffset_ = 0; + } + } + isFlushed_ = true; + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_writeChunk].methodExit(); + } + } + + void writeChunkThrowIO(String str) throws IOException + { + if (JdbcDebugCfg.entryActive) debug[methodId_writeChunkThrowIO].methodEntry(); + try + { + try + { + writeChunk(str); + } + catch (SQLException e) + { + throw new IOException(SQLMXLob.convSQLExceptionToIO(e)); + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_writeChunkThrowIO].methodExit(); + } + } + + void populate(Reader ir, int length) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_populate].methodEntry(); + try + { + int tempLen; + int readLen; + int retLen; + + readLen = length; + try + { + while (readLen > 0) + { + if (readLen <= clob_.chunkSize_) + tempLen = readLen; + else + tempLen = clob_.chunkSize_; + retLen = ir.read(chunk_, 0, tempLen); + if (retLen == -1) + break; + currentChar_ = retLen; + + if ((traceWriter_ != null) && + ((traceFlag_ == T2Driver.LOB_LVL) || (traceFlag_ == T2Driver.ENTRY_LVL))) + { + // For tracing, only print the 1st and last LOB data chunk write info to limit + // potential overflow of buffer for trace output. + if (readLen==length) // 1st writeChunk + { + traceWriter_.println(getTraceId() + + "populate() - First writeChunk data: tableName_=" + clob_.tableName_ + + " dataLocator_=" + clob_.dataLocator_ + " length=" + length + + " currentChunkNo_=" + currentChunkNo_ + " updChunkNo_=" + updChunkNo_ + " retLen=" + retLen); + } + if (readLen<=clob_.chunkSize_) // last writeChunk (NOTE: last chunk can be exactly chunkSize_) + { + traceWriter_.println(getTraceId() + + "populate() - Last writeChunk data: tableName_=" + clob_.tableName_ + + " dataLocator_=" + clob_.dataLocator_ + " length=" + length + + " currentChunkNo_=" + currentChunkNo_ + " updChunkNo_=" + updChunkNo_ + " retLen=" + retLen); + } + } + + writeChunk(null); + readLen -= retLen; + } + } + catch (IOException e) + { + Object[] messageArguments = new Object[1]; + messageArguments[0] = e.getMessage(); + throw Messages.createSQLException(conn_.locale_, "io_exception", + messageArguments); + } + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_populate].methodExit(); + } + } + + // constructors + SQLMXClobWriter(SQLMXConnection connection, SQLMXClob clob, long pos) throws SQLException + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClobWriter].methodEntry(); + try + { + long length; + + clob_ = clob; + length = clob_.length(); + conn_ = connection; + if (pos < 1 || pos > length+1) + throw Messages.createSQLException(conn_.locale_,"invalid_position_value", null); + startingPos_ = pos; + chunk_ = new char[clob_.chunkSize_]; + isFlushed_ = false; + if (length == 0) + updChunkNo_ = -1; + else + { + if ((length % clob_.chunkSize_) == 0) + updChunkNo_ = (int)(length / clob_.chunkSize_)-1; + else + updChunkNo_ = (int)(length / clob_.chunkSize_); + } + currentChunkNo_ = (int)((pos-1)/ clob_.chunkSize_); + currentChar_ = (int)((pos-1) % clob_.chunkSize_); + updOffset_ = (int)((pos-1) % clob_.chunkSize_); + + + } + finally + { + if (JdbcDebugCfg.entryActive) debug[methodId_SQLMXClobWriter].methodExit(); + } + } + public void setTraceId(String traceId_) { + this.traceId_ = traceId_; + } + + public String getTraceId() { + traceWriter_ = SQLMXDataSource.traceWriter_; + + // Build up template portion of jdbcTrace output. Pre-appended to jdbcTrace entries. + // jdbcTrace:[XXXX]:[Thread[X,X,X]]:[XXXXXXXX]:ClassName. + if (traceWriter_ != null) + { + traceFlag_ = T2Driver.traceFlag_; + String className = getClass().getName(); + setTraceId(T2Driver.traceText + T2Driver.dateFormat.format(new Date()) + + "]:[" + Thread.currentThread() + "]:[" + hashCode() + "]:" + + className.substring(T2Driver.REMOVE_PKG_NAME,className.length()) + + "."); + } + return traceId_; + } + + // Fields + private String traceId_; + static PrintWriter traceWriter_; + static int traceFlag_; + SQLMXClob clob_; + long startingPos_; + SQLMXConnection conn_; + boolean isClosed_; + char[] chunk_; + int currentChar_; + int currentChunkNo_; + boolean isFlushed_; + int updChunkNo_; + int updOffset_; + + private static int methodId_close = 0; + private static int methodId_flush = 1; + private static int methodId_write_C = 2; + private static int methodId_write_CII = 3; + private static int methodId_write_I = 4; + private static int methodId_write_L = 5; + private static int methodId_write_LII = 6; + private static int methodId_writeChunk = 7; + private static int methodId_writeChunkThrowIO = 8; + private static int methodId_populate = 9; + private static int methodId_SQLMXClobWriter = 10; + private static int totalMethodIds = 11; + private static JdbcDebug[] debug; + + static + { + String className = "SQLMXClobWriter"; + if (JdbcDebugCfg.entryActive) + { + debug = new JdbcDebug[totalMethodIds]; + debug[methodId_close] = new JdbcDebug(className,"close"); + debug[methodId_flush] = new JdbcDebug(className,"flush"); + debug[methodId_write_C] = new JdbcDebug(className,"write[C]"); + debug[methodId_write_CII] = new JdbcDebug(className,"write[CII]"); + debug[methodId_write_I] = new JdbcDebug(className,"write[I]"); + debug[methodId_write_L] = new JdbcDebug(className,"write[L]"); + debug[methodId_write_LII] = new JdbcDebug(className,"write[LII]"); + debug[methodId_writeChunk] = new JdbcDebug(className,"writeChunk"); + debug[methodId_writeChunkThrowIO] = new JdbcDebug(className,"writeChunkThrowIO"); + debug[methodId_populate] = new JdbcDebug(className,"populate"); + debug[methodId_SQLMXClobWriter] = new JdbcDebug(className,"SQLMXClobWriter"); + } + } +}