All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdev.lang.cmd.Query Maven / Gradle / Ivy

/*
 * XDEV Application Framework - XDEV Application Framework
 * Copyright © 2003 XDEV Software (https://xdev.software)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 */
package xdev.lang.cmd;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import xdev.db.DBConnection;
import xdev.db.DBDataSource;
import xdev.db.DBException;
import xdev.db.DBUtils;
import xdev.db.Result;
import xdev.db.sql.Column;
import xdev.db.sql.Condition;
import xdev.db.sql.Expression;
import xdev.db.sql.Functions;
import xdev.db.sql.SELECT;
import xdev.db.sql.Table;
import xdev.vt.VirtualTable;
import xdev.vt.VirtualTableColumn;
import xdev.vt.VirtualTableException;
import xdev.vt.VirtualTableFillMethod;


public abstract class Query extends XdevCommandObject
{
	@Target(ElementType.METHOD)
	@Retention(RetentionPolicy.RUNTIME)
	public static @interface SqlFunction
	{
	}
	


	@Target(ElementType.PARAMETER)
	@Retention(RetentionPolicy.RUNTIME)
	public static @interface ColumnNamePossible
	{
	}
	
	private DBDataSource				dataSource;
	protected final SELECT				select;
	private List						parameters;
	private VirtualTable				virtualTable;
	private List	targetColumns;
	private VirtualTableFillMethod		fillMethod;
	private String						primaryTable;
	private Map			tableCache		= new HashMap();
	private Map		aliasCounter	= new HashMap();
	

	public Query(Object... args)
	{
		super(args);
		
		select = new SELECT();
		parameters = new ArrayList();
		targetColumns = new ArrayList();
		fillMethod = VirtualTableFillMethod.OVERWRITE;
		aliasCounter = new HashMap();
	}
	

	public void setDataSource(DBDataSource dataSource)
	{
		this.dataSource = dataSource;
	}
	

	public Query select(String column)
	{
		select.columns(getColumn(column));
		return this;
	}
	

	public Query select(String table, String column)
	{
		if(primaryTable == null || !table.equals(primaryTable))
		{
			select.columns(new Column(getTableWithAlias(table,false),column));
		}
		else
		{
			select.columns(getColumn(table,column));
		}
		
		return this;
	}
	

	public Query select2(Object expression)
	{
		select.columns(expression);
		return this;
	}
	

	public void into(VirtualTableColumn column)
	{
		if(column != null)
		{
			select.ensureNameOfLastColumn(column.getName());
		}
		
		targetColumns.add(column);
	}
	

	public void from(String table)
	{
		primaryTable = table;
		select.FROM(new Table(table));
	}
	

	public void innerJoin(String table, String column, String table2, String column2)
	{
		Table sqlTable = getTableWithAlias(table,true);
		Table sqlTable2 = new Table(table2);
		select.INNER_JOIN(sqlTable,new Column(sqlTable,column).eq(new Column(sqlTable2,column2)));
	}
	

	public void outerJoin(String table, String column, String table2, String column2)
	{
		Table sqlTable = getTableWithAlias(table,true);
		Table sqlTable2 = new Table(table2);
		select.OUTER_JOIN(sqlTable,new Column(sqlTable,column).eq(new Column(sqlTable2,column2)));
	}
	

	public void leftJoin(String table, String column, String table2, String column2)
	{
		Table sqlTable = getTableWithAlias(table,true);
		Table sqlTable2 = new Table(table2);
		select.LEFT_JOIN(sqlTable,new Column(sqlTable,column).eq(new Column(sqlTable2,column2)));
	}
	

	public void rightJoin(String table, String column, String table2, String column2)
	{
		Table sqlTable = getTableWithAlias(table,true);
		Table sqlTable2 = new Table(table2);
		select.RIGHT_JOIN(sqlTable,new Column(sqlTable,column).eq(new Column(sqlTable2,column2)));
	}
	

	public void innerJoin(String table, Object condition)
	{
		select.INNER_JOIN(new Table(table),condition);
	}
	

	public void outerJoin(String table, Object condition)
	{
		select.OUTER_JOIN(new Table(table),condition);
	}
	

	public void leftJoin(String table, Object condition)
	{
		select.LEFT_JOIN(new Table(table),condition);
	}
	

	public void rightJoin(String table, Object condition)
	{
		select.RIGHT_JOIN(new Table(table),condition);
	}
	

	public void where(Object condition, Object... params)
	{
		select.WHERE(condition);
		addParameters(params);
	}
	

	public void addParameters(Object... params)
	{
		if(params != null && params.length > 0)
		{
			Collections.addAll(this.parameters,params);
		}
	}
	

	public Condition condition(Object condition)
	{
		return Condition.valueOf(condition);
	}
	

	public void groupBy(Object... fields)
	{
		select.GROUP_BY(fields);
	}
	

	public void having(Object condition, Object... params)
	{
		select.HAVING(condition);
		
		if(params != null && params.length > 0)
		{
			parameters.addAll(Arrays.asList(params));
		}
	}
	
	public final static int	ORDER_DEFAULT	= 0;
	public final static int	ORDER_ASC		= 1;
	public final static int	ORDER_DESC		= 2;
	
	public final static int	NULLS_DEFAULT	= 0;
	public final static int	NULLS_FIRST		= 1;
	public final static int	NULLS_LAST		= 2;
	

	public void orderBy(String column, int order, int nulls)
	{
		orderBy(getColumn(column),order,nulls);
	}
	

	public void orderBy(String table, String column, int order, int nulls)
	{
		orderBy(getColumn(table,column),order,nulls);
	}
	

	private void orderBy(Column column, int order, int nulls)
	{
		Boolean desc = null;
		switch(order)
		{
			case ORDER_ASC:
				desc = Boolean.FALSE;
			break;
			case ORDER_DESC:
				desc = Boolean.TRUE;
			break;
		}
		
		Boolean nullsFirst = null;
		switch(nulls)
		{
			case NULLS_FIRST:
				nullsFirst = Boolean.TRUE;
			break;
			case NULLS_LAST:
				nullsFirst = Boolean.FALSE;
			break;
		}
		
		select.ORDER_BY(column,desc,nullsFirst);
	}
	

	public void orderBy(Object item)
	{
		select.ORDER_BY(item);
	}
	

	public void offset(int offset)
	{
		select.OFFSET(offset);
	}
	

	public void limit(int limit)
	{
		select.FETCH_FIRST(limit);
	}
	

	public Condition parenthesis(Object condition)
	{
		return Condition.par(condition);
	}
	

	public Column getColumn(String column)
	{
		return new Column(column);
	}
	

	public Column getColumn(String table, String column)
	{
		return new Column(new Table(table),column);
	}
	

	public Table getTable(String name)
	{
		return new Table(name);
	}
	

	private Table getTableWithAlias(String table, boolean newAliasIfExists)
	{
		Table sqlTable = tableCache.get(table);
		if(sqlTable == null)
		{
			sqlTable = new Table(table);
			if(newAliasIfExists)
			{
				tableCache.put(table,sqlTable);
			}
		}
		else if(newAliasIfExists)
		{
			Integer nr = aliasCounter.get(table);
			if(nr == null)
			{
				nr = 2;
			}
			else
			{
				nr++;
			}
			sqlTable = sqlTable.AS(sqlTable.getTableName() + nr);
			aliasCounter.put(table,nr);
			tableCache.put(table,sqlTable);
		}
		return sqlTable;
	}
	

	public Object LIKE_(Object expression)
	{
		return String.valueOf(expression).concat("%");
	}
	

	public Object _LIKE(Object expression)
	{
		return "%".concat(String.valueOf(expression));
	}
	

	public Object _LIKE_(Object expression)
	{
		return "%".concat(String.valueOf(expression)).concat("%");
	}
	

	/**
	 * Returns the average value of a numeric column.
	 * 
	 * @param expression
	 *            the name of the column
	 */
	@SqlFunction
	public Expression AVG(@ColumnNamePossible Object expression)
	{
		return Functions.AVG(expression);
	}
	

	/**
	 * Returns the number of rows in a query.
	 * 
	 * @param expression
	 *            the expression to count the rows of, e.g. a column name
	 */
	@SqlFunction
	public Expression COUNT(@ColumnNamePossible Object expression)
	{
		return Functions.COUNT(expression);
	}
	

	/**
	 * Returns the number of rows in a query - COUNT(*).
	 */
	@SqlFunction
	public Expression COUNT_ALL()
	{
		return Functions.COUNT();
	}
	

	/**
	 * Returns the largest value of the selected column.
	 * 
	 * @param expression
	 *            the name of the column
	 */
	@SqlFunction
	public Expression MAX(@ColumnNamePossible Object expression)
	{
		return Functions.MAX(expression);
	}
	

	/**
	 * Returns the smallest value of the selected column.
	 * 
	 * @param expression
	 *            the name of the column
	 */
	@SqlFunction
	public Expression MIN(@ColumnNamePossible Object expression)
	{
		return Functions.MIN(expression);
	}
	

	/**
	 * Returns the total sum of a numeric column.
	 * 
	 * @param expression
	 *            the name of the column
	 */
	@SqlFunction
	public Expression SUM(@ColumnNamePossible Object expression)
	{
		return Functions.SUM(expression);
	}
	

	/**
	 * Returns the absolute value of a numeric column or expression.
	 * 
	 * @param expression
	 *            the name of the column or a numeric expression
	 */
	@SqlFunction
	public Expression ABS(@ColumnNamePossible Object expression)
	{
		return Functions.ABS(expression);
	}
	

	/**
	 * Converts an expression of one data type to another.
	 * 
	 * @param type
	 *            the type to convert to
	 * @param expression
	 *            the value to convert
	 */
	// @SqlFunction
	// public Expression CAST(Object type, Object expression)
	// {
	// return new SqlFunctionCAST(type,expression);
	// }
	
	/**
	 * Returns the first non-null expression among the arguments.
	 * 
	 * @param values
	 *            the table column names or value value expressions
	 */
	@SqlFunction
	public Expression COALESCE(@ColumnNamePossible Object... values)
	{
		return Functions.COALESCE(values);
	}
	

	/**
	 * Returns the remainder of the division from 2 integer values.
	 * 
	 * @param dividend
	 *            the dividend
	 * @param divisor
	 *            the divisor
	 */
	@SqlFunction
	public Expression MOD(@ColumnNamePossible Object dividend, @ColumnNamePossible Object divisor)
	{
		return Functions.MOD(dividend,divisor);
	}
	
	/**
	 * Rounds a numeric field to the number of decimals specified.
	 * 

* This method is not supported by some databases. * * @param value * column name or numeric expression * @param decimals * the number of decimals to round to */ @SqlFunction public Expression ROUND(@ColumnNamePossible Object value, int decimals) { return Functions.ROUND(value,decimals); } public void setVirtualTable(VirtualTable virtualTable) { this.virtualTable = virtualTable; } public void setFillMethod(VirtualTableFillMethod fillMethod) { this.fillMethod = fillMethod; } @Override public void execute() throws DBException, VirtualTableException { if(dataSource == null) { dataSource = DBUtils.getCurrentDataSource(); } if(dataSource == null) { CommandException.throwMissingParameter("dataSource"); } if(select == null) { CommandException.throwMissingParameter("select"); } if(virtualTable == null) { CommandException.throwMissingParameter("virtualTable"); } DBConnection connection = dataSource.openConnection(); try { Result result = connection.query(select,this.parameters.toArray()); try { int columnCount; if(targetColumns != null && (columnCount = targetColumns.size()) > 0) { // get actual columns if vt has been cloned VirtualTableColumn[] columns = targetColumns .toArray(new VirtualTableColumn[columnCount]); for(int i = 0; i < columnCount; i++) { if(columns[i] != null) { columns[i] = virtualTable.getColumn(columns[i].getName()); } } virtualTable.addData(result,columns,fillMethod); } else { virtualTable.addData(result,fillMethod); } } finally { result.close(); } } finally { connection.close(); } } public VirtualTable getVirtualTable() { return virtualTable; } @Override public String toString() { return select.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy