001 package org.apache.ojb.broker.util;
002
003 /* Copyright 2002-2005 The Apache Software Foundation
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 import java.sql.ResultSet;
019 import java.sql.SQLException;
020
021 import org.apache.commons.lang.StringUtils;
022
023 /**
024 * Helper class for all SQL related stuff.
025 *
026 * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel </a>
027 * @version $Id: SqlHelper.java,v 1.1 2007-08-24 22:17:36 ewestfal Exp $
028 */
029 public class SqlHelper
030 {
031 /** define the name of the pseudo column holding the class to be instantiated. */
032 public static final String OJB_CLASS_COLUMN = "OJB_CLAZZ";
033
034 /**
035 * Helper Class for a split column <br>
036 * ie: sum (distinct amount) as theAmount
037 *
038 * <pre>
039 * prefix = 'sum (distinct '
040 * column = 'amount'
041 * suffix = ') as theAmount'
042 * </pre>
043 */
044 public static final class PathInfo
045 {
046 public String column;
047 public String prefix;
048 public String suffix;
049 public final String path; //original Path
050
051 PathInfo(String aPath, String aPrefix, String aColumn, String aSuffix)
052 {
053 path = aPath;
054 column = aColumn;
055 prefix = aPrefix;
056 suffix = aSuffix;
057 }
058 }
059
060 /**
061 * remove functions and () from path <br>
062 * ie: avg(amount) -> amount <br>
063 * ie: sum (accounts.amount) -> accounts.amount <br>
064 * ie: count(distinct id) as theCount-> id <br>
065 *
066 * @param aPath
067 * the path to the attribute
068 */
069 public static String cleanPath(String aPath)
070 {
071 return splitPath(aPath).column;
072 }
073
074 /**
075 * Split a path into column , prefix and suffix, the prefix contains all
076 * info up to the column <br>
077 * ie: avg(amount) -> amount , avg( , )<br>
078 * ie: sum (accounts.amount) as theSum -> accounts.amount , sum( , ) as
079 * theSum <br>
080 * ie: count( distinct id ) as bla -> id , count(distinct , ) as bla <br>
081 * Supports simple expressions ie: price * 1.05
082 *
083 * TODO: cannot resolve multiple attributes in expression
084 * ie: price - bonus
085 *
086 * @param aPath
087 * @return PathInfo
088 */
089 public static PathInfo splitPath(String aPath)
090 {
091 String prefix = null;
092 String suffix = null;
093 String colName = aPath;
094
095 if (aPath == null)
096 {
097 return new PathInfo(null, null, null, null);
098 }
099
100 // ignore leading ( and trailing ) ie: sum(avg(col1))
101 int braceBegin = aPath.lastIndexOf("(");
102 int braceEnd = aPath.indexOf(")");
103 int opPos = StringUtils.indexOfAny(aPath, "+-/*");
104
105 if (braceBegin >= 0 && braceEnd >= 0 && braceEnd > braceBegin)
106 {
107 int colBegin;
108 int colEnd;
109 String betweenBraces;
110
111 betweenBraces = aPath.substring(braceBegin + 1, braceEnd).trim();
112 // look for ie 'distinct name'
113 colBegin = betweenBraces.indexOf(" ");
114 // look for multiarg function like to_char(col,'format_mask')
115 colEnd = betweenBraces.indexOf(",");
116 colEnd = colEnd > 0 ? colEnd : betweenBraces.length();
117 prefix = aPath.substring(0, braceBegin + 1) + betweenBraces.substring(0, colBegin + 1);
118 colName = betweenBraces.substring(colBegin + 1, colEnd);
119 suffix = betweenBraces.substring(colEnd) + aPath.substring(braceEnd);
120 }
121 else if (opPos >= 0)
122 {
123 colName = aPath.substring(0, opPos).trim();
124 suffix = aPath.substring(opPos);
125 }
126
127 return new PathInfo(aPath, prefix, colName.trim(), suffix);
128 }
129
130 /**
131 * Returns the name of the class to be instantiated.
132 * @param rs the Resultset
133 * @return null if the column is not available
134 */
135 public static String getOjbClassName(ResultSet rs)
136 {
137 try
138 {
139 return rs.getString(OJB_CLASS_COLUMN);
140 }
141 catch (SQLException e)
142 {
143 return null;
144 }
145 }
146
147 }