blob: 420be5dfc02c9090fda941a0633b6061bfe4d5b8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.empire.db;
import java.util.Collection;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.OptionEntry;
import org.apache.empire.data.DataType;
import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.dbms.DBSqlPhrase;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* DBSQLBuilder
* This class is used for building a single SQL statement
* @author doebele
*/
public abstract class DBSQLBuilder implements Appendable
{
private static final Logger log = LoggerFactory.getLogger(DBSQLBuilder.class);
private final DBMSHandler dbms;
private final StringBuilder sql = new StringBuilder(64);
private DBCmdParamList cmdParamList;
/**
* Don't use this directly
* Use dbms.createSQLBuilder()
*/
protected DBSQLBuilder(DBMSHandler dbms)
{
this.dbms = dbms;
}
public void setCmdParams(DBCmdParamList cmdParamList)
{
this.cmdParamList = cmdParamList;
}
/*
* getters
*/
public DBMSHandler getDbms()
{
return dbms;
}
public String getPhrase(DBSqlPhrase phrase)
{
return dbms.getSQLPhrase(phrase);
}
/*
* special
*/
public int length()
{
return sql.length();
}
public void reset(int pos)
{
if (pos>sql.length())
throw new InvalidArgumentException("pos", pos);
sql.setLength(pos);
}
/*
* appenders
*/
@Override
public DBSQLBuilder append(CharSequence sqlLiteral)
{
sql.append(sqlLiteral);
return this;
}
@Override
public DBSQLBuilder append(CharSequence sqlLiteral, int start, int end)
{
sql.append(sqlLiteral, start, end);
return this;
}
public DBSQLBuilder append(DBSqlPhrase phrase)
{
sql.append(dbms.getSQLPhrase(phrase));
return this;
}
public void append(DBCommandExpr subQueryCmd)
{
// subQueryCmd.addSQL(this, DBExpr.CTX_DEFAULT);
sql.append(subQueryCmd.getSelect());
DBCmdParams params = subQueryCmd.getParams();
if (params.isEmpty())
return;
cmdParamList.mergeSubqueryParams(params);
/*
// Check CmdParams
Object[] paramValues = subQueryCmd.getParamValues();
if (paramValues!=null && paramValues.length>0)
{ // Params Available
cmdParamList.mergeSubqueryParams(paramValues);
}
*/
}
@Override
public DBSQLBuilder append(char c)
{
sql.append(c);
return this;
}
public DBSQLBuilder append(boolean b) {
sql.append(b);
return this;
}
public DBSQLBuilder append(int i) {
sql.append(i);
return this;
}
public DBSQLBuilder append(long l) {
sql.append(l);
return this;
}
public DBSQLBuilder append(float f) {
sql.append(f);
return this;
}
public DBSQLBuilder append(double d) {
sql.append(d);
return this;
}
/**
* Appends the SQL representation of a value
*
* @param StringBuilder but the SQL builder
* @param dataType the DataType
* @param value an DBExpr object, array or a basis data type(e.g. int, String)
* @param context the context of the DBColumnExpr object
* @param arraySep the separator value
* @return the new SQL-Command
*/
public void appendValue(DataType dataType, Object value, long context, String arraySep)
{
// it's an Object
if (value instanceof DBExpr)
{ // it's an expression
((DBExpr) value).addSQL(this, context);
return;
}
// check option entry
if (value instanceof OptionEntry)
{ // option value
value = ((OptionEntry)value).getValue();
}
// check enum
if (value instanceof Enum<?>)
{ // check enum
value = ObjectUtils.getEnumValue((Enum<?>)value, dataType.isNumeric());
}
else if (value instanceof Collection<?>)
{ // collection 2 array
value = ((Collection<?>)value).toArray();
}
// Check whether it is an array
if (value!=null && value.getClass().isArray())
{ // An Array of Objects
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++)
{ // Array Separator
if (i > 0 && arraySep != null)
sql.append(arraySep);
// Append Value
appendValue(dataType, array[i], context, arraySep);
}
return;
}
else
{ // Get Value Expression from dmbs
sql.append(dbms.getValueString(value, dataType));
}
}
/**
* Expands an SQL template and adds it to the SQL command
*
* @param StringBuilder but the SQL builder
* @param template the SQL template
* @param values an array of values to be inserted into the template
* @param dataType the DataType
* @param context the context of the DBColumnExpr object
* @param arraySep the separator value
* @return the new SQL-Command
*/
public void appendTemplate(String template, Object[] values, DataType[] dataTypes, long context, String arraySep)
{
int pos = 0;
while (true)
{
// find begin
int beg = template.indexOf('{', pos);
if (beg < 0)
break;
// append
sql.append(template.substring(pos, beg));
// find end
int end = template.indexOf('}', ++beg);
if (end < 0)
throw new InvalidArgumentException("template", template);
// part
int iParam = Integer.parseInt(template.substring(beg, end));
if (iParam<0 || iParam>=values.length)
throw new InvalidArgumentException("params", values);
// add value
DataType dataType = (dataTypes.length>=iParam ? dataTypes[iParam] : dataTypes[0]);
appendValue(dataType, values[iParam], context, arraySep);
// next
pos = end + 1;
}
if (pos < template.length())
{ // add the rest
sql.append(template.substring(pos));
// special case: Nothing added yet
if (pos==0 && values!=null && values.length>0)
log.warn("No Placeholder for found in template {}!", template);
}
}
/**
* returns the SQL as a String
*/
@Override
public String toString()
{
return sql.toString();
}
}