blob: 0deefb16bcb7c5c94591bfcdc6266830097e3931 [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.ArrayList;
import java.util.Iterator;
import org.apache.empire.data.DataType;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.UnspecifiedErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* DBCmdParamList
* This class handles command parameters for Prepared Statements
*/
public class DBCmdParamList implements DBCmdParams
{
protected static final Logger log = LoggerFactory.getLogger(DBCmdParamList.class);
protected ArrayList<DBCmdParam> cmdParams;
private int paramUsageCount = 0;
public DBCmdParamList()
{
cmdParams = null;
}
public DBCmdParamList(int size)
{
cmdParams = (size>0 ? new ArrayList<>(size) : null);
}
@Override
public boolean isEmpty()
{
return (cmdParams==null || cmdParams.isEmpty());
}
@Override
public int size()
{
return (cmdParams==null ? 0 : cmdParams.size());
}
@Override
public Iterator<DBCmdParam> iterator()
{
if (cmdParams==null)
throw new NotSupportedException(this, "iterator");
return cmdParams.iterator();
}
public void clear(int capacity)
{
paramUsageCount = 0;
if (capacity>0)
cmdParams= new ArrayList<DBCmdParam>(capacity);
else
cmdParams = null;
}
public void add(DBCmdParam param)
{
if (cmdParams==null)
cmdParams= new ArrayList<DBCmdParam>();
// Create and add the parameter to the parameter list
cmdParams.add(param);
}
public void remove(DBCmdParam param)
{
if (cmdParams==null || !cmdParams.remove(param))
log.warn("Unable to remove DBCmdParam: Param not found");
}
public Object[] getParamValues()
{
if (cmdParams==null || paramUsageCount==0)
return null;
// Check whether all parameters have been used
if (paramUsageCount!=cmdParams.size())
log.info("DBCommand parameter count ("+String.valueOf(cmdParams.size())
+ ") does not match parameter use count ("+String.valueOf(paramUsageCount)+")");
// Create result array
Object[] values = new Object[paramUsageCount];
for (int i=0; i<values.length; i++)
values[i]=cmdParams.get(i).getValue();
// values
return values;
}
/**
* internally used to reset the command param usage count.
* Note: Only one thread my generate an SQL statement
*/
public void resetParamUsage(DBCommand cmd)
{
paramUsageCount = 0;
if (cmdParams==null)
return;
// clear subquery params
for (int i=cmdParams.size()-1; i>=0 ;i--)
if (cmdParams.get(i).getCmd()!=cmd)
cmdParams.remove(i);
}
/**
* internally used to remove unused Command Params from list
* Note: Only one thread my generate an SQL statement
*/
public void completeParamUsage(DBCommand cmd)
{
if (cmdParams==null)
return;
// check whether all params have been used
if (paramUsageCount < cmdParams.size())
{ // Remove unused parameters
log.warn("DBCommand has {} unused Command params", cmdParams.size()-paramUsageCount);
for (int i=cmdParams.size()-1; i>=paramUsageCount; i--)
{ // Remove temporary params
if (cmdParams.get(i).getCmd()!=cmd)
cmdParams.remove(i);
}
}
}
/**
* internally used to reorder the command params to match their order of occurance
*/
protected void notifyParamUsage(DBCmdParam param)
{
int index = cmdParams.indexOf(param);
if (index<0)
{ // Error: parameter probably used twice in statement!
throw new UnspecifiedErrorException("The CmdParam has not been found on this Command.");
}
if (index < paramUsageCount)
{ // Warn: parameter used twice in statement!
log.debug("The DBCmdParam already been used. Adding a temporary copy");
cmdParams.add(paramUsageCount, new DBCmdParam(null, param.getDataType(), param.getValue()));
}
else if (index > paramUsageCount)
{ // Correct parameter order
cmdParams.remove(index);
cmdParams.add(paramUsageCount, param);
}
paramUsageCount++;
}
public void mergeSubqueryParams(DBCmdParams subQueryParams)
{
if (subQueryParams==null || subQueryParams.isEmpty())
return;
// Subquery has parameters
if (cmdParams==null)
cmdParams= new ArrayList<DBCmdParam>(subQueryParams.size());
for (DBCmdParam p : subQueryParams)
cmdParams.add(paramUsageCount++, new DBCmdParam(null, DataType.UNKNOWN, p.getValue()));
}
/*
protected void mergeSubqueryParamsObsolete(Object[] subQueryParams)
{
if (subQueryParams==null || subQueryParams.length==0)
return;
// Subquery has parameters
if (cmdParams==null)
cmdParams= new ArrayList<DBCmdParam>(subQueryParams.length);
for (int p=0; p<subQueryParams.length; p++)
cmdParams.add(paramUsageCount++, new DBCmdParam(null, DataType.UNKNOWN, subQueryParams[p]));
log.warn("mergeSubqueryParamsObsolete");
}
public void addJoin(DBSQLBuilder sql, DBJoinExpr join, long context, int whichParams)
{
// remember insert pos
int paramInsertPos = paramUsageCount;
// now add the join
join.addSQL(sql, context);
// Merge subquery params
Object[] subQueryParams = join.getSubqueryParams(whichParams);
if (subQueryParams!=null)
{
if (paramInsertPos == paramUsageCount)
mergeSubqueryParamsObsolete(subQueryParams);
else
{ // Some Params have been used in additional Join constraints
int tempCounter = paramUsageCount;
paramUsageCount = paramInsertPos;
mergeSubqueryParamsObsolete(subQueryParams);
int insertCount = (paramUsageCount - paramInsertPos);
paramUsageCount = tempCounter + insertCount;
}
}
}
*/
}