KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > sql > Util


1 /**
2  * com.mckoi.database.sql.Util 08 Jul 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database.sql;
26
27 import com.mckoi.database.Expression;
28 import com.mckoi.database.Operator;
29 import com.mckoi.database.FunctionDef;
30 import com.mckoi.database.Variable;
31 import com.mckoi.database.TableName;
32 import com.mckoi.database.TObject;
33 import com.mckoi.database.TType;
34 import com.mckoi.database.global.*;
35 import com.mckoi.util.BigNumber;
36
37 /**
38  * Various utility methods for the iterpreter.
39  *
40  * @author Tobias Downer
41  */

42
43 public class Util {
44
45   private static TObject ZERO_NUMBER = TObject.intVal(0);
46   
47   /**
48    * Returns the Token as a non quoted reference. For example, a
49    * QUOTED_VARIABLE token will have the first and last '"' character
50    * removed. A QUOTED_DELIMINATED_REF will have " removed in each deliminated
51    * section. For example, '"re1"."re2"."a"' becomes 're1.re2.a" and
52    * '"re1.re2.a"' becomes 're1.re2.a'.
53    */

54   public static String JavaDoc asNonQuotedRef(Token token) {
55     if (token.kind == SQLConstants.QUOTED_VARIABLE) {
56       // Strip " from start and end if a quoted variable
57
return token.image.substring(1, token.image.length() - 1);
58     }
59     else if (token.kind == SQLConstants.QUOTED_DELIMINATED_REF ||
60              token.kind == SQLConstants.QUOTEDGLOBVARIABLE) {
61       // Remove all " from the string
62
String JavaDoc image = token.image;
63       StringBuffer JavaDoc b = new StringBuffer JavaDoc();
64       int sz = image.length();
65       for (int i = 0; i < sz; ++i) {
66         char c = image.charAt(i);
67         if (c != '\"') {
68           b.append(c);
69         }
70       }
71       return new String JavaDoc(b);
72     }
73     else {
74       return token.image;
75     }
76   }
77
78   /**
79    * Converts a Token which is either a STRING_LITERAL, NUMBER_LITERAL or
80    * IDENTIFIER into a Java Object. If 'upper_identifiers' is true then all
81    * identifiers are made upper case before being returned (eg. if the
82    * object returns is a Variable object).
83    */

84   public static Object JavaDoc toParamObject(Token token, boolean upper_identifiers) {
85     if (token.kind == SQLConstants.STRING_LITERAL) {
86       String JavaDoc raw_string = token.image.substring(1, token.image.length() - 1);
87       return TObject.stringVal(escapeTranslated(raw_string));
88     }
89 // else if (token.kind == SQLConstants.NUMBER_LITERAL) {
90
// return TObject.bigNumberVal(BigNumber.fromString(token.image));
91
// }
92
else if (token.kind == SQLConstants.BOOLEAN_LITERAL) {
93       return TObject.booleanVal(token.image.equalsIgnoreCase("true"));
94     }
95     else if (token.kind == SQLConstants.NULL_LITERAL) {
96       return TObject.nullVal();
97     }
98     else if (token.kind == SQLConstants.REGEX_LITERAL) {
99       // Horrible hack,
100
// Get rid of the 'regex' string at the start,
101
String JavaDoc str = token.image.substring(5).trim();
102       return TObject.stringVal(str);
103     }
104     else if (token.kind == SQLConstants.QUOTED_VARIABLE ||
105              token.kind == SQLConstants.GLOBVARIABLE || // eg. Part.*
106
token.kind == SQLConstants.IDENTIFIER ||
107              token.kind == SQLConstants.DOT_DELIMINATED_REF ||
108              token.kind == SQLConstants.QUOTED_DELIMINATED_REF) {
109       String JavaDoc name = asNonQuotedRef(token);
110 // if (token.kind == SQLConstants.QUOTED_VARIABLE) {
111
// name = token.image.substring(1, token.image.length() - 1);
112
// }
113
// else {
114
// name = token.image;
115
// }
116
if (upper_identifiers) {
117         name = name.toUpperCase();
118       }
119       Variable v;
120       int div = name.lastIndexOf(".");
121       if (div != -1) {
122         // Column represents '[something].[name]'
123
// Check if the column name is an alias.
124
String JavaDoc column_name = name.substring(div + 1);
125         // Make the '[something]' into a TableName
126
TableName table_name = TableName.resolve(name.substring(0, div));
127
128         // Set the variable name
129
v = new Variable(table_name, column_name);
130       }
131       else {
132         // Column represents '[something]'
133
v = new Variable(name);
134       }
135       return v;
136     }
137     else { // Otherwise it must be a reserved word, so just return the image
138
// as a variable.
139
String JavaDoc name = token.image;
140       if (upper_identifiers) {
141         name = name.toUpperCase();
142       }
143       return new Variable(token.image);
144     }
145   }
146
147   /**
148    * Returns numeric 0
149    */

150   public static TObject zeroNumber() {
151     return ZERO_NUMBER;
152   }
153
154   /**
155    * Parses a NUMBER_LITERAL Token with a sign boolean.
156    */

157   public static TObject parseNumberToken(Token token, boolean negative) {
158     if (negative) {
159       return TObject.bigNumberVal(BigNumber.fromString("-" + token.image));
160     }
161     else {
162       return TObject.bigNumberVal(BigNumber.fromString(token.image));
163     }
164   }
165   
166   /**
167    * Converts an expression array to an array type that can be added to an
168    * expression.
169    */

170   public static TObject toArrayParamObject(Expression[] arr) {
171     return new TObject(TType.ARRAY_TYPE, arr);
172   }
173   
174   /**
175    * Returns an array of Expression objects as a comma deliminated string.
176    */

177   public static String JavaDoc expressionListToString(Expression[] list) {
178     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
179     for (int i = 0; i < list.length; ++i) {
180       buf.append(list[i].text().toString());
181       if (i < list.length - 1) {
182         buf.append(", ");
183       }
184     }
185     return new String JavaDoc(buf);
186   }
187
188   /**
189    * Normalizes the Expression by removing all NOT operators and altering
190    * the expression as appropriate. For example, the expression;
191    * not ((a + b) = c and c = 5)
192    * would be normalized to;
193    * (a + b) <> c or c <> 5
194    */

195   public static Expression normalize(final Expression exp) {
196     // Only normalize if the expression contains a NOT operator.
197
if (exp.containsNotOperator()) {
198       return normalize(exp, false);
199     }
200     return exp;
201   }
202
203   /**
204    * Normalizes the Expression by removing all NOT operators and altering
205    * the expression as appropriate. For example, the expression;
206    * not ((a + b) = c and c = 5)
207    * would be normalized to;
208    * (a + b) <> c or c <> 5
209    */

210   private static Expression normalize(final Expression exp,
211                                       final boolean inverse) {
212     if (exp.size() <= 1) {
213       if (inverse) {
214         return standardInverse(exp);
215       }
216       else {
217         return exp;
218       }
219     }
220     final Operator op = (Operator) exp.last();
221     final Expression[] exps = exp.split();
222
223     if (op.isNot()) {
224       // If the operator is NOT then return the normalized form of the LHS.
225
// We toggle the inverse flag.
226
return normalize(exps[0], !inverse);
227     }
228     else if (op.isNotInversible()) {
229       // If the operator is not inversible, return the expression with a
230
// '= false' if nothing else is possible
231
Expression resolved_expr =
232              new Expression(normalize(exps[0], false), op,
233                             normalize(exps[1], false));
234       if (inverse) {
235         return standardInverse(resolved_expr);
236       }
237       else {
238         return resolved_expr;
239       }
240     }
241     else if (op.isLogical()) {
242       // If logical we inverse the operator and inverse the left and right
243
// side of the operator also.
244
if (inverse) {
245         return new Expression(normalize(exps[0], inverse), op.inverse(),
246                               normalize(exps[1], inverse));
247       }
248       else {
249         return new Expression(normalize(exps[0], inverse), op,
250                               normalize(exps[1], inverse));
251
252       }
253     }
254     else {
255       // By this point we can assume the operator is naturally inversible.
256
if (inverse) {
257         return new Expression(normalize(exps[0], false), op.inverse(),
258                               normalize(exps[1], false));
259       }
260       else {
261         return new Expression(normalize(exps[0], false), op,
262                               normalize(exps[1], false));
263       }
264     }
265
266   }
267
268   /**
269    * Returns an expression that is (exp) = false which is the natural
270    * inverse of all expressions. This should only be used if the expression
271    * can't be inversed in any other way.
272    */

273   private static Expression standardInverse(Expression exp) {
274     return new Expression(exp, Operator.get("="),
275                           new Expression(TObject.booleanVal(false)));
276   }
277
278   /**
279    * Returns a Function object that represents the name and expression list
280    * (of parameters) of a function. Throws an exception if the function
281    * doesn't exist.
282    */

283   public static FunctionDef resolveFunctionName(String JavaDoc name,
284                                                 Expression[] exp_list) {
285     return new FunctionDef(name, exp_list);
286   }
287
288   /**
289    * Translate a string with escape codes into a un-escaped Java string. \' is
290    * converted to ', \n is a newline, \t is a tab, \\ is \, etc.
291    */

292   private static String JavaDoc escapeTranslated(String JavaDoc input) {
293     StringBuffer JavaDoc result = new StringBuffer JavaDoc();
294     int size = input.length();
295     boolean last_char_escape = false;
296     boolean last_char_quote = false;
297     for (int i = 0; i < size; ++i) {
298       char c = input.charAt(i);
299       if (last_char_quote) {
300         last_char_quote = false;
301         if (c != '\'') {
302           result.append(c);
303         }
304       }
305       else if (last_char_escape) {
306         if (c == '\\') {
307           result.append('\\');
308         }
309         else if (c == '\'') {
310           result.append('\'');
311         }
312         else if (c == 't') {
313           result.append('\t');
314         }
315         else if (c == 'n') {
316           result.append('\n');
317         }
318         else if (c == 'r') {
319           result.append('\r');
320         }
321         else {
322           result.append('\\');
323           result.append(c);
324         }
325         last_char_escape = false;
326       }
327       else if (c == '\\') {
328         last_char_escape = true;
329       }
330       else if (c == '\'') {
331         last_char_quote = true;
332         result.append(c);
333       }
334       else {
335         result.append(c);
336       }
337     }
338     return new String JavaDoc(result);
339   }
340
341 }
342
Popular Tags