001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.storage.search.implementation.database;
011:
012: import org.mmbase.bridge.Field;
013: import org.mmbase.storage.search.*;
014: import org.mmbase.util.logging.*;
015:
016: /**
017: * The MySQL query handler, implements {@link
018: * org.mmbase.storage.search.implementation.database.SqlHandler SqlHandler} for standard
019: * MySQL functionality.
020: * <br />
021: * Derived from {@link BasicSqlHandler BasicSqlHandler}, overrides
022: * <ul>
023: * <li>{@link #toSql toSql()}, implements {@link
024: * org.mmbase.storage.search.SearchQueryHandler#FEATURE_MAX_NUMBER
025: * FEATURE_MAX_NUMBER} and {@link
026: * org.mmbase.storage.search.SearchQueryHandler#FEATURE_OFFSET
027: * FEATURE_OFFSET}, by adding a construct like "<code>LIMIT 20</code>" or
028: * "<code>LIMIT 80, 20</code>" after the body, when appropriate.
029: * <li>{@link #getSupportLevel(int,SearchQuery) getSupportLevel(int,SearchQuery)},
030: * returns {@link
031: * org.mmbase.storage.search.SearchQueryHandler#SUPPORT_OPTIMAL
032: * SUPPORT_OPTIMAL} for these features, delegates to the superclass for
033: * other features.
034: * </ul>
035: *
036: * @author Rob van Maris
037: * @version $Id: MySqlSqlHandler.java,v 1.20 2007/06/12 10:59:41 michiel Exp $
038: * @since MMBase-1.7
039: */
040: public class MySqlSqlHandler extends BasicSqlHandler implements
041: SqlHandler {
042:
043: private static final Logger log = Logging
044: .getLoggerInstance(MySqlSqlHandler.class);
045:
046: /**
047: * Constructor.
048: */
049: public MySqlSqlHandler() {
050: super ();
051: }
052:
053: @Override
054: protected String toSqlString(String str) {
055: String res = super .toSqlString(str).replaceAll("\\\\",
056: "\\\\\\\\");
057: return res;
058: }
059:
060: // javadoc is inherited
061: @Override
062: public int getSupportLevel(int feature, SearchQuery query)
063: throws SearchQueryException {
064: int result;
065: switch (feature) {
066: case SearchQueryHandler.FEATURE_MAX_NUMBER:
067: result = SearchQueryHandler.SUPPORT_OPTIMAL;
068: break;
069:
070: case SearchQueryHandler.FEATURE_OFFSET:
071: result = SearchQueryHandler.SUPPORT_OPTIMAL;
072: break;
073: /*
074: case SearchQueryHandler.FEATURE_REGEXP:
075: result = SearchQueryHandler.SUPPORT_OPTIMAL;
076: break;
077: */
078: default:
079: result = super .getSupportLevel(feature, query);
080: }
081: return result;
082: }
083:
084: // javadoc inherited
085: @Override
086: protected boolean useLower(FieldCompareConstraint constraint) {
087: return true; // necessary for the larger strings which are stored in blobs
088: }
089:
090: @Override
091: protected StringBuilder appendLikeOperator(StringBuilder sb,
092: boolean caseSensitive) {
093: if (caseSensitive) {
094: sb.append(" LIKE BINARY ");
095: } else {
096: sb.append(" LIKE ");
097: }
098: return sb;
099: }
100:
101: /*
102: protected StringBuilder appendRegularExpressionOperator(StringBuilder sb, boolean caseSensitive) {
103: if (caseSensitive) {
104: sb.append(" REGEXP BINARY ");
105: } else {
106: sb.append(" REGEXP ");
107: }
108: return sb;
109: }
110: */
111:
112: /**
113: * @javadoc
114: */
115: @Override
116: protected void appendDateField(StringBuilder sb, Step step,
117: String fieldName, boolean multipleSteps, int datePart) {
118: String datePartFunction = null;
119: switch (datePart) {
120: case FieldValueDateConstraint.CENTURY:
121: datePartFunction = "CENTURY";
122: break;
123: case FieldValueDateConstraint.QUARTER:
124: datePartFunction = "QUARTER";
125: break;
126: case FieldValueDateConstraint.WEEK:
127: datePartFunction = "WEEK";
128: break;
129: case FieldValueDateConstraint.DAY_OF_YEAR:
130: datePartFunction = "DAYOFYEAR";
131: break;
132: case FieldValueDateConstraint.DAY_OF_WEEK:
133: datePartFunction = "DAYOFWEEK";
134: break;
135: default:
136: log.debug("Unknown datePart " + datePart);
137: }
138: if (datePartFunction != null) {
139: sb.append(datePartFunction);
140: sb.append("(");
141: appendField(sb, step, fieldName, multipleSteps);
142: sb.append(")");
143: } else {
144: super .appendDateField(sb, step, fieldName, multipleSteps,
145: datePart);
146: }
147: }
148:
149: @Override
150: protected StringBuilder appendSortOrderField(StringBuilder sb,
151: SortOrder sortOrder, boolean multipleSteps) {
152: if (sortOrder.isCaseSensitive()
153: && sortOrder.getField().getType() == Field.TYPE_STRING) {
154: sb.append("BINARY ");
155: }
156: // Fieldname.
157: appendField(sb, sortOrder, multipleSteps);
158: return sb;
159: }
160:
161: // javadoc is inherited
162: @Override
163: public String toSql(SearchQuery query, SqlHandler firstInChain)
164: throws SearchQueryException {
165: // XXX should table and field aliases be tested for uniqueness?
166:
167: // Test for at least 1 step and 1 field.
168: if (query.getSteps().isEmpty()) {
169: throw new IllegalStateException(
170: "Searchquery has no step (at leas 1 step is required).");
171: }
172: if (query.getFields().isEmpty()) {
173: throw new IllegalStateException(
174: "Searchquery has no field (at least 1 field is required).");
175: }
176:
177: // SELECT
178: StringBuilder sbQuery = new StringBuilder("SELECT ");
179:
180: // DISTINCT
181: if (query.isDistinct()) {
182: sbQuery.append("DISTINCT ");
183: }
184:
185: firstInChain.appendQueryBodyToSql(sbQuery, query, firstInChain);
186:
187: // LIMIT
188: if (query.getMaxNumber() != -1) {
189: // Maxnumber set.
190: sbQuery.append(" LIMIT ");
191: if (query.getOffset() != 0) {
192: sbQuery.append(query.getOffset()).append(",");
193: }
194: sbQuery.append(query.getMaxNumber());
195: } else {
196: // Offset > 0, maxnumber not set.
197: if (query.getOffset() != 0) {
198: sbQuery.append(" LIMIT ").append(query.getOffset())
199: .append(",").append(Integer.MAX_VALUE);
200: }
201: }
202:
203: String strSQL = sbQuery.toString();
204: if (log.isDebugEnabled()) {
205: log.debug("generated SQL: " + strSQL);
206: }
207: return strSQL;
208: }
209: }
|