com.caucho.db.sql.SelectQuery Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.db.sql;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.caucho.db.Database;
import com.caucho.db.table.TableIterator;
import com.caucho.db.xa.DbTransaction;
import com.caucho.env.shutdown.ExitCode;
import com.caucho.env.shutdown.ShutdownSystem;
import com.caucho.util.CharBuffer;
import com.caucho.util.L10N;
import com.caucho.util.SQLExceptionWrapper;
public class SelectQuery extends Query {
private static final L10N L = new L10N(SelectQuery.class);
private static final Logger log
= Logger.getLogger(SelectQuery.class.getName());
private Expr []_results;
private String []_resultNames;
private boolean []_groupFields;
private Order _order;
private int _limit = Integer.MAX_VALUE / 2;
SelectQuery(Database db, String sql)
throws SQLException
{
super(db, sql);
}
SelectQuery(Database db, String sql, FromItem []fromItems)
throws SQLException
{
super(db, sql, fromItems);
}
void setResults(Expr []resultExprs)
throws SQLException
{
_results = new Expr[resultExprs.length];
for (int i = 0; i < resultExprs.length; i++) {
_results[i] = resultExprs[i];
}
setDataFields(resultExprs.length);
}
Expr []getResults()
{
return _results;
}
/**
* Sets the result item as group.
*/
public void setGroupResult(int index)
{
if (_groupFields == null)
_groupFields = new boolean[_results.length];
_groupFields[index] = true;
}
@Override
protected void bind()
throws SQLException
{
super.bind();
for (int i = 0; i < _results.length; i++) {
_results[i] = _results[i].bind(this);
}
if (isGroup()) {
for (int i = 0; i < _results.length; i++) {
if (isGroup() && ! (_results[i] instanceof GroupExpr))
_results[i] = new GroupResultExpr(i, _results[i]);
}
}
for (int i = 0; i < _results.length; i++) {
_results[i] = _results[i].bind(this);
}
_resultNames = new String[_results.length];
for (int i = 0; i < _resultNames.length; i++)
_resultNames[i] = _results[i].getName();
}
void setOrder(Order order)
{
_order = order;
}
@Override
public void setLimit(int limit)
{
_limit = limit;
}
/**
* Returns true for select queries.
*/
@Override
public boolean isSelect()
{
return true;
}
/**
* Returns the type of the child.
*/
Class> getType()
{
if (_results.length == 1)
return _results[0].getType();
else
return Object.class;
}
/**
* Executes the query.
*/
@Override
public void execute(QueryContext context, DbTransaction xa)
throws SQLException
{
SelectResult result = SelectResult.create(_results, _order);
FromItem []fromItems = getFromItems();
TableIterator []rows = null;
try {
rows = result.initRows(fromItems);
context.init(xa, rows, isReadOnly());
if (isGroup())
executeGroup(result, rows, context, xa);
else
execute(result, rows, context, xa);
result.initRead();
context.setResult(result);
} catch (IOException e) {
throw new SQLExceptionWrapper(e);
} catch (IllegalStateException exn) {
log.log(Level.WARNING, exn.toString(), exn);
ShutdownSystem.shutdownActive(ExitCode.HEALTH,
L.l("Internal database issue: forcing restart {0}",
exn.toString()));
} finally {
// autoCommitRead must be before freeRows in case freeRows
// throws an exception
try {
context.close();
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
if (rows != null)
freeRows(rows, rows.length);
}
}
/**
* Executes the query.
*/
private void execute(SelectResult result,
TableIterator []rows,
QueryContext context,
DbTransaction xa)
throws SQLException, IOException
{
FromItem []fromItems = getFromItems();
int rowLength = fromItems.length;
int limit = _limit;
int contextLimit = context.getLimit();
if (contextLimit > 0) {
limit = contextLimit;
}
if (start(rows, rowLength, context, xa)) {
do {
result.startRow();
for (int i = 0; i < _results.length; i++) {
_results[i].evalToResult(context, result);
}
} while (nextTuple(rows, rowLength, context, xa) && --limit > 0);
}
}
private void executeGroup(SelectResult result,
TableIterator []rows,
QueryContext context,
DbTransaction transaction)
throws SQLException, IOException
{
FromItem []fromItems = getFromItems();
int rowLength = fromItems.length;
Expr []results = _results;
int resultsLength = results.length;
/*
for (int i = 0; i < results.length; i++)
results[i].initGroup(context);
*/
if (_groupFields == null)
_groupFields = new boolean[0];
boolean []groupByFields = _groupFields;
int groupByLength = _groupFields.length;
if (start(rows, rowLength, context, transaction)) {
do {
context.initGroup(getDataFields(), _groupFields);
for (int i = 0; i < groupByLength; i++) {
if (groupByFields[i])
results[i].evalGroup(context);
}
context.selectGroup();
for (int i = 0; i < resultsLength; i++) {
if (! (i < groupByLength && groupByFields[i]))
results[i].evalGroup(context);
}
} while (nextTuple(rows, rowLength, context, transaction));
}
Iterator groupIter = context.groupResults();
while (groupIter.hasNext()) {
GroupItem item = groupIter.next();
context.setGroupItem(item);
result.startRow();
for (int i = 0; i < results.length; i++) {
results[i].evalToResult(context, result);
}
}
}
/**
* Executes the query.
*/
@Override
public SelectCursor executeCursor(QueryContext context, DbTransaction xa)
throws SQLException
{
if (isGroup())
throw new IllegalStateException();
if (_order != null)
throw new IllegalStateException();
FromItem []fromItems = getFromItems();
TableIterator []rows = null;
SelectCursor cursor = new SelectCursor(_results, this, context);
rows = cursor.initRows(fromItems);
context.init(xa, rows, isReadOnly());
int rowLength = fromItems.length;
if (start(rows, rowLength, context, xa)) {
context.unlock();
return cursor;
}
else
return null;
}
/**
* Executes the query.
*/
public final boolean nextCursor(TableIterator []rows,
QueryContext context,
DbTransaction xa)
throws SQLException
{
try {
FromItem []fromItems = getFromItems();
int rowLength = fromItems.length;
boolean value = nextTuple(rows, rowLength, context, xa);
return value;
} catch (IOException e) {
throw new SQLExceptionWrapper(e);
}
}
public String toString()
{
CharBuffer cb = CharBuffer.allocate();
cb.append("SelectQuery[");
cb.append("SELECT ");
if (_results != null) {
for (int i = 0; i < _results.length; i++) {
if (i != 0)
cb.append(",");
cb.append(_results[i]);
}
}
else {
cb.append("... unknown ...");
}
cb.append(" FROM ");
FromItem []fromItems = getFromItems();
for (int i = 0; i < fromItems.length; i++) {
if (i != 0)
cb.append(",");
cb.append(fromItems[i]);
}
if (_whereExpr != null) {
cb.append(" WHERE " + _whereExpr);
}
cb.append("]");
return cb.close();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy