001: //
002: // Copyright 1998 CDS Networks, Inc., Medford Oregon
003: //
004: // All rights reserved.
005: //
006: // Redistribution and use in source and binary forms, with or without
007: // modification, are permitted provided that the following conditions are met:
008: // 1. Redistributions of source code must retain the above copyright
009: // notice, this list of conditions and the following disclaimer.
010: // 2. Redistributions in binary form must reproduce the above copyright
011: // notice, this list of conditions and the following disclaimer in the
012: // documentation and/or other materials provided with the distribution.
013: // 3. All advertising materials mentioning features or use of this software
014: // must display the following acknowledgement:
015: // This product includes software developed by CDS Networks, Inc.
016: // 4. The name of CDS Networks, Inc. may not be used to endorse or promote
017: // products derived from this software without specific prior
018: // written permission.
019: //
020: // THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
021: // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: // ARE DISCLAIMED. IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
024: // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
025: // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
026: // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
027: // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
028: // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
029: // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
030: // SUCH DAMAGE.
031: //
032:
033: package com.internetcds.jdbc.tds;
034:
035: import java.sql.*;
036: import java.util.StringTokenizer;
037: import java.util.Vector;
038:
039: public class Procedure {
040: public static final String cvsVersion = "$Id: Procedure.java,v 1.2 2007-10-19 13:21:40 sinisa Exp $";
041:
042: ParameterListItem parameterList[] = null;
043: String sqlProcedureName = null;
044: String rawQueryString = null;
045: String procedureString = "";
046:
047: private Tds tds = null;
048: private boolean hasLobs = false;
049:
050: private void init(String rawSql_, String sqlProcedureName_,
051: ParameterListItem[] parameterList_, Tds tds_)
052: throws SQLException {
053: int i;
054:
055: rawQueryString = rawSql_;
056: sqlProcedureName = sqlProcedureName_;
057: tds = tds_;
058:
059: // need a clone to keep the maxlength information for char data
060: parameterList = new ParameterListItem[parameterList_.length];
061: for (i = 0; i < parameterList.length; i++) {
062: parameterList[i] = (ParameterListItem) parameterList_[i]
063: .clone();
064: }
065:
066: // make sure all the parameters are set
067: ParameterUtils.verifyThatParametersAreSet(parameterList);
068:
069: // make sure we have the same number of placeholders as
070: // item in the parameter list.
071: if (parameterList.length != ParameterUtils
072: .countParameters(rawQueryString)) {
073: throw new SQLException(
074: "Number of parametrs in sql statement "
075: + "does not match the number of parameters "
076: + " in parameter list");
077: }
078:
079: // Create the procedure text
080: {
081: procedureString = "create proc " + sqlProcedureName;
082:
083: // Create actual to formal parameter mapping
084: ParameterUtils.createParameterMapping(rawQueryString,
085: parameterList, tds);
086:
087: // copy back the formal types and check for LOBs
088: for (i = 0; i < parameterList.length; i++) {
089: parameterList_[i].formalType = parameterList[i].formalType;
090:
091: if (parameterList[i].formalType
092: .equalsIgnoreCase("image")
093: || parameterList[i].formalType
094: .equalsIgnoreCase("text")
095: || parameterList[i].formalType
096: .equalsIgnoreCase("ntext")) {
097: hasLobs = true;
098: }
099: }
100:
101: // add the formal parameter list to the sql string
102: procedureString = procedureString
103: + createFormalParameterList(parameterList);
104:
105: procedureString = procedureString + " as ";
106:
107: // Go through the raw sql and substitute a parameter name
108: // for each '?' placeholder in the raw sql
109:
110: StringTokenizer st = new StringTokenizer(rawQueryString,
111: "'?\\", true);
112: final int normal = 1;
113: final int inString = 2;
114: final int inEscape = 3;
115: int state = normal;
116: String current;
117: int nextParameterIndex = 0;
118:
119: while (st.hasMoreTokens()) {
120: current = st.nextToken();
121: switch (state) {
122: case normal: {
123: if (current.equals("?")) {
124: procedureString = procedureString
125: + "@"
126: + parameterList[nextParameterIndex].formalName;
127: nextParameterIndex++;
128: } else if (current.equals("'")) {
129: procedureString = procedureString + current;
130: state = inString;
131: } else {
132: procedureString = procedureString + current;
133: }
134: break;
135: }
136: case inString: {
137: if (current.equals("'")) {
138: state = normal;
139: } else if (current.equals("\\")) {
140: state = inEscape;
141: } else {
142: // nop
143: }
144: procedureString = procedureString + current;
145: break;
146: }
147: case inEscape: {
148: state = inString;
149: procedureString = procedureString + current;
150: break;
151: }
152: default: {
153: throw new SQLException(
154: "Internal error. Bad State " + state);
155: }
156: }
157: }
158: }
159: }
160:
161: public Procedure(String rawSql_, String sqlProcedureName_,
162: ParameterListItem[] parameterList_, Tds tds_)
163: throws SQLException {
164: init(rawSql_, sqlProcedureName_, parameterList_, tds_);
165: }
166:
167: public String getPreparedSqlString() {
168: return procedureString;
169: }
170:
171: public String getProcedureName() {
172: return sqlProcedureName;
173: }
174:
175: public ParameterListItem getParameter(int index) {
176: return parameterList[index];
177: }
178:
179: private String createFormalParameterList(
180: ParameterListItem[] parameterList) {
181: int i;
182: String result;
183:
184: if (parameterList.length == 0) {
185: result = "";
186: } else {
187: result = "(";
188: for (i = 0; i < parameterList.length; i++) {
189: if (i > 0) {
190: result = result + ", ";
191: }
192: result = result + "@" + parameterList[i].formalName
193: + " " + parameterList[i].formalType;
194: }
195: result = result + ")";
196: }
197: return result;
198: }
199:
200: /**
201: * This method checks to see if the actual parameters are compatible
202: * with the formal parameters for this procedure.
203: *
204: */
205: public boolean compatibleParameters(
206: ParameterListItem actualParams[]) throws SQLException {
207: int i;
208: boolean isOkay = true;
209:
210: isOkay = parameterList.length == actualParams.length;
211:
212: for (i = 0; isOkay && i < actualParams.length; i++) {
213: if ((parameterList[i].formalType.startsWith("char")
214: || parameterList[i].formalType
215: .startsWith("varchar")
216: || parameterList[i].formalType.startsWith("text")
217: || parameterList[i].formalType.startsWith("nchar")
218: || parameterList[i].formalType
219: .startsWith("nvarchar") || parameterList[i].formalType
220: .startsWith("ntext"))
221: && (actualParams[i].type == java.sql.Types.CHAR
222: || actualParams[i].type == java.sql.Types.VARCHAR || actualParams[i].type == java.sql.Types.LONGVARCHAR)) {
223: isOkay = parameterList[i].maxLength >= actualParams[i].maxLength;
224: } else {
225: isOkay = parameterList[i].formalType
226: .equalsIgnoreCase(actualParams[i].formalType);
227: }
228: }
229: return isOkay;
230: }
231:
232: public ParameterListItem[] getParameterList() {
233: return parameterList;
234: }
235:
236: /**
237: * Does the formal parameter list include LOB parameters?
238: */
239: public boolean hasLobParameters() {
240: return hasLobs;
241: }
242: }
|