/*
* 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.ignite.internal.processors.query.h2.sql;
import java.util.ArrayList;
import java.util.List;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
/**
* SQL Query AST.
*/
public abstract class GridSqlQuery extends GridSqlStatement implements GridSqlAst {
/** */
public static final int OFFSET_CHILD = 0;
/** */
public static final int LIMIT_CHILD = 1;
/** */
protected List<GridSqlSortColumn> sort = new ArrayList<>();
/** */
private GridSqlAst offset;
/**
* @return Offset.
*/
public GridSqlAst offset() {
return offset;
}
/**
* @param offset Offset.
*/
public void offset(GridSqlAst offset) {
this.offset = offset;
}
/**
* @return Sort.
*/
public List<GridSqlSortColumn> sort() {
return sort;
}
/**
*
*/
public void clearSort() {
sort = new ArrayList<>();
}
/**
* @param sortCol The sort column.
*/
public void addSort(GridSqlSortColumn sortCol) {
sort.add(sortCol);
}
/**
* @return Number of visible columns.
*/
protected abstract int visibleColumns();
/**
* @param col Column index.
* @return Expression for column index.
*/
protected abstract GridSqlAst column(int col);
/** {@inheritDoc} */
@Override public GridSqlType resultType() {
return GridSqlType.RESULT_SET;
}
/** {@inheritDoc} */
@Override public <E extends GridSqlAst> E child() {
return child(0);
}
/** {@inheritDoc} */
@Override public <E extends GridSqlAst> E child(int childIdx) {
switch (childIdx) {
case OFFSET_CHILD:
return maskNull(offset, GridSqlPlaceholder.EMPTY);
case LIMIT_CHILD:
return maskNull(limit, GridSqlPlaceholder.EMPTY);
default:
throw new IllegalStateException("Child index: " + childIdx);
}
}
/**
* @param x Element.
* @return Empty placeholder if the element is {@code null}.
*/
@SuppressWarnings("unchecked")
protected static <E extends GridSqlAst> E maskNull(GridSqlAst x, GridSqlAst dflt) {
return (E)(x == null ? dflt : x);
}
/** {@inheritDoc} */
@Override public <E extends GridSqlAst> void child(int childIdx, E child) {
switch (childIdx) {
case OFFSET_CHILD:
offset = child;
break;
case LIMIT_CHILD:
limit = child;
break;
default:
throw new IllegalStateException("Child index: " + childIdx);
}
}
/**
* @return If this is a simple query with no conditions, expressions, sorting, etc...
*/
public abstract boolean simpleQuery();
/**
* @param buff Statement builder.
*/
protected void getSortLimitSQL(StatementBuilder buff) {
if (!sort.isEmpty()) {
buff.append("\nORDER BY ");
int visibleCols = visibleColumns();
buff.resetCount();
for (GridSqlSortColumn col : sort) {
buff.appendExceptFirst(", ");
int idx = col.column();
assert idx >= 0 : idx;
if (idx < visibleCols)
buff.append(idx + 1);
else {
GridSqlAst expr = column(idx);
if (expr == null) // For plain select should never be null, for union H2 itself can't parse query.
throw new IllegalStateException("Failed to build query: " + buff.toString());
if (expr instanceof GridSqlAlias)
expr = expr.child(0);
buff.append('=').append(StringUtils.unEnclose(expr.getSQL()));
}
if (!col.asc())
buff.append(" DESC");
if (col.nullsFirst())
buff.append(" NULLS FIRST");
else if (col.nullsLast())
buff.append(" NULLS LAST");
}
}
if (limit != null)
buff.append(" LIMIT ").append(StringUtils.unEnclose(limit.getSQL()));
if (offset != null)
buff.append(" OFFSET ").append(StringUtils.unEnclose(offset.getSQL()));
}
}