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:
038: // import java.util.Vector;
039:
040: public class ParameterUtils {
041: public static final String cvsVersion = "$Id: ParameterUtils.java,v 1.2 2007-10-19 13:21:40 sinisa Exp $";
042:
043: /**
044: * Count the number of parameters in a prepared sql statement.
045: *
046: * @return number of parameter placeholders in sql statement.
047: * @exception SQLException thrown if there is a problem parsing statment.
048: */
049: public static int countParameters(String sql)
050: throws java.sql.SQLException {
051: //
052: // This is method is implemented as a very simple finite state machine.
053: //
054:
055: int result = 0;
056:
057: if (sql == null) {
058: throw new SQLException("No statement");
059: } else {
060: StringTokenizer st = new StringTokenizer(sql, "'?\\", true);
061: final int normal = 1;
062: final int inString = 2;
063: final int inEscape = 3;
064: int state = normal;
065: String current;
066:
067: while (st.hasMoreTokens()) {
068: current = st.nextToken();
069: switch (state) {
070: case normal: {
071: if (current.equals("?")) {
072: result++;
073: } else if (current.equals("'")) {
074: state = inString;
075: } else {
076: // nop
077: }
078: break;
079: }
080: case inString: {
081: if (current.equals("'")) {
082: state = normal;
083: } else if (current.equals("\\")) {
084: state = inEscape;
085: } else {
086: // nop
087: }
088: break;
089: }
090: case inEscape: {
091: state = inString;
092: break;
093: }
094: default: {
095: throw new SQLException(
096: "Internal error. Bad State " + state);
097: }
098: }
099: }
100: }
101:
102: return result;
103: }
104:
105: /**
106: * check that all items in parameterList have been given a value
107: *
108: * @exception SQLException thrown if one or more parameters aren't set
109: */
110: public static void verifyThatParametersAreSet(
111: ParameterListItem[] parameterList) throws SQLException {
112:
113: int i;
114: boolean okay = true;
115:
116: for (i = 0; okay && i < parameterList.length; i++) {
117: okay = okay && parameterList[i].isSet;
118: if (!okay) {
119: throw new SQLException("parameter #" + (i + 1)
120: + " has not been set");
121: }
122: }
123:
124: }
125:
126: /**
127: * create the formal parameters for a parameter list.
128: *
129: * This method takes a sql string and a parameter list containing
130: * the actual parameters and creates the formal parameters for
131: * a stored procedure. The formal parameters will later be used
132: * when the stored procedure is submitted for creation on the server.
133: *
134: * @param rawQueryString (in-only)
135: * @param parameterList (update)
136: *
137: */
138: public static void createParameterMapping(String rawQueryString,
139: ParameterListItem[] parameterList, Tds tds)
140: throws SQLException {
141:
142: int i;
143: String nextFormal;
144: int nextParameterNumber = 0;
145: int tdsVer = tds.getTdsVer();
146: EncodingHelper encoder = tds.getEncoder();
147:
148: for (i = 0; i < parameterList.length; i++) {
149: do {
150: nextParameterNumber++;
151: nextFormal = "P" + nextParameterNumber;
152: } while (-1 != rawQueryString.indexOf(nextFormal));
153:
154: parameterList[i].formalName = nextFormal;
155:
156: switch (parameterList[i].type) {
157: case java.sql.Types.VARCHAR:
158: case java.sql.Types.CHAR: {
159: String value = (String) parameterList[i].value;
160: if (value == null) {
161: // use the smalles case possible for nulls
162: parameterList[i].formalType = "varchar(255)";
163: parameterList[i].maxLength = 255;
164:
165: } else if (tdsVer == Tds.TDS70) {
166: /*
167: * SQL Server 7 can handle Unicode so use it wherever
168: * possible
169: */
170:
171: if (value.length() < 4001) {
172: parameterList[i].formalType = "nvarchar(4000)";
173: parameterList[i].maxLength = 4000;
174: } else if (value.length() < 8001
175: && !encoder.isDBCS()
176: && encoder.canBeConverted(value)) {
177: parameterList[i].formalType = "varchar(8000)";
178: parameterList[i].maxLength = 8000;
179: } else {
180: parameterList[i].formalType = "ntext";
181: parameterList[i].maxLength = Integer.MAX_VALUE;
182: }
183: } else {
184: int len = value.length();
185: if (encoder.isDBCS() && len > 127 && len < 256) {
186: len = encoder.getBytes(value).length;
187: }
188:
189: if (len < 256) {
190: parameterList[i].formalType = "varchar(255)";
191: parameterList[i].maxLength = 255;
192: } else {
193: parameterList[i].formalType = "text";
194: parameterList[i].maxLength = Integer.MAX_VALUE;
195: }
196: }
197: break;
198: }
199: case java.sql.Types.LONGVARCHAR: {
200: if (tdsVer == Tds.TDS70) {
201: parameterList[i].formalType = "ntext";
202: } else {
203: parameterList[i].formalType = "text";
204: }
205: parameterList[i].maxLength = Integer.MAX_VALUE;
206: break;
207: }
208: case java.sql.Types.INTEGER:
209: case java.sql.Types.SMALLINT:
210: case java.sql.Types.BIGINT: {
211: parameterList[i].formalType = "integer";
212: break;
213: }
214: case java.sql.Types.REAL: {
215: parameterList[i].formalType = "real";
216: break;
217: }
218: //sinisa
219: //implement DECIMAL as formal type real for procedure parameters
220: case java.sql.Types.DECIMAL: {
221: parameterList[i].formalType = "real";
222: break;
223: }
224: case java.sql.Types.DOUBLE:
225: // case java.sql.Types.FLOAT:
226: // case java.sql.Types.DECIMAL:
227: {
228: parameterList[i].formalType = "float";
229: break;
230: }
231: case java.sql.Types.TIMESTAMP:
232: case java.sql.Types.DATE:
233: case java.sql.Types.TIME: {
234: parameterList[i].formalType = "datetime";
235: break;
236: }
237: case java.sql.Types.LONGVARBINARY:
238: case java.sql.Types.VARBINARY: {
239: parameterList[i].formalType = "image";
240: break;
241: }
242: //Dusan
243: case java.sql.Types.BIT: {
244: parameterList[i].formalType = "bit";
245: break;
246: }
247: case java.sql.Types.BINARY:
248: //case java.sql.Types.BIT:
249: //Sinisa
250: //java.sql.Types.DECIMAL implemented
251: //case java.sql.Types.DECIMAL:
252: case java.sql.Types.FLOAT:
253: case java.sql.Types.NULL:
254: case java.sql.Types.NUMERIC:
255: case java.sql.Types.OTHER:
256: case java.sql.Types.TINYINT: {
257: throw new SQLException(
258: "Not implemented (type is ("
259: + TdsUtil
260: .javaSqlTypeToString(parameterList[i].type)
261: + ")");
262: }
263: default: {
264: throw new SQLException(
265: "Internal error. Unrecognized type "
266: + parameterList[i].type);
267: }
268: }
269: }
270: }
271:
272: }
|