SimpleSqlQuery.java

package org.microspace.table.query;

import java.util.List;

import org.microspace.space.SimpleSpace;
import org.microspace.table.Entry;
import org.microspace.table.column.Accessor;
import org.microspace.table.column.ColumnReferences;
import org.microspace.table.column.IndexedMap;
import org.microspace.table.query.sql.Select;
import org.microspace.table.query.sql.SimpleSqlBuilder;
import org.microspace.util.UniqueId;


/**
 * Query using simplified version of SQL.
 * <p>
 * Here is the grammar (AntlrSimpleSql.g4):
  * <p>
 * Examples
 * <pre>
 
 SELECT * FROM org.microspace.RichRecord ORDER BY familyName, givenName
 
 SELECT * FROM org.microspace.RichRecord ORDER BY familyName, givenName ASC
 
 SELECT * FROM org.microspace.RichRecord ORDER BY familyName, givenName DESC
  
 SELECT * FROM org.microspace.RichRecord WHERE familyName = 'Sinai';
 
 SELECT * FROM org.microspace.RichRecord WHERE familyName = 'Sinai' AND ROWNUM &lt; 0;
 
 SELECT * FROM org.microspace.RichRecord WHERE familyName LIKE 'Sinai%';
 
 SELECT * FROM org.microspace.RichRecord WHERE country IN ( 'GERMANY', 'JAPAN' )
 
 SELECT * FROM org.microspace.RichRecord WHERE country IN ( SELECT ...
 
 SELECT DISTINCT familyName, givenName FROM org.microspace.RichRecord
  
 </pre>
 * @author Gaspar Sinai - {@literal gaspar.sinai@microspace.org}
 * @version 2019-09-29
 */
public class SimpleSqlQuery<T> implements TableQuery<T> {
	
	private final Class<T> tableClass;
	private final String queryString;
	private final Select<T> select;
	private final UniqueId spaceId;
	@SuppressWarnings("unused")
	private final String qid;
	
	/**
	 * Create a query, guessing table class from select statement.
	 * <p>
	 * This method is for internal use. Please use {@link SimpleSqlQuery#build(String)} instead.
	 * 
	 * @param queryString The SELECT query.
	 */
	private SimpleSqlQuery (String queryString) {
		this(queryString, null);
	}
	/**
	 * Create a type checked query.
	 * 
	 * @param queryString The SELECT query.
	 * @param tableClass The Table class.
	 */
	public SimpleSqlQuery (String queryString, Class<T> tableClass) {
		this(queryString, tableClass, null);
	}
	
	/**
	 * Create a type checked query.
	 * 
	 * @param queryString The SELECT query.
	 * @param tableClass The Table class.
	 * @param spaceId is the spaceId restriction or null.
	 */
	public SimpleSqlQuery (String queryString, Class<T> tableClass, UniqueId spaceId) {
		this.queryString = queryString;
		SimpleSqlBuilder<T> builder = new SimpleSqlBuilder<T> (queryString, tableClass);
		this.select = builder.getSelect();
		this.tableClass = this.select.getTableClass();
		this.spaceId = spaceId;
		if (spaceId == null) {
			this.qid = queryString;
		} else {
			this.qid = spaceId.toString() + ": " + queryString;
		}
	}

	/**
	 * Build a SELECT query using a String.
	 * @param queryString The query String.
	 * @return The TableQuery.
	 * @param <T> The table type.
	 */
	public static <T> SimpleSqlQuery<T> build (String queryString) {
		return new SimpleSqlQuery<T> (queryString);
	}
	/**
	 * Build a query using a SELECT parsed query.
	 * 
	 * @param select The parsed query.
	 */
	public SimpleSqlQuery (Select<T> select) {
		this(select, null);
	}	

	/**
	 * Build a query using a SELECT parsed query.
	 * 
	 * @param select The parsed query.
	 * @param spaceId is the spaceId restriction or null.
	 */
	public SimpleSqlQuery (Select<T> select, UniqueId spaceId) {
		this.select = select;
		this.queryString = select.getId();
		this.tableClass = select.getTableClass();
		this.spaceId = spaceId;
		if (spaceId == null) {
			this.qid = queryString;
		} else {
			this.qid = spaceId.toString() + ": " + queryString;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public IndexedMap<Object, Entry<T>> getMatchingEntries(Accessor<T> accessor, IndexedMap<Object, Entry<T>> entries,
			ColumnReferences<T>[] indexedColumns) {
		return select.apply(accessor, entries, indexedColumns);
	}
	
	/**
	 * {@inheritDoc}
	 */
	public List<Entry<T>> sortAndLimit (Accessor<T> accessor, 
			IndexedMap<Object, Entry<T>> entries) {
		return select.sortAndLimit(accessor, entries);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean match(T object, Accessor<T> accessor) {
		return select.match(object, accessor);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Class<T> getTableClass() {
		return tableClass;
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		return queryString;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getId() {
		if (spaceId == null) {
			return queryString;
		}
		return spaceId.toString() + ": " + queryString;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareQuery(SimpleSpace space) {
		select.setInnerSelectContext(space);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void finishQuery() {
		select.clearInnerSelectContext();
	}

	public String formatSqlQuery (SqlFormat format) {
		return select.formatSqlQuery(format);
	}
	@Override
	public UniqueId getSpaceId() {
		return spaceId;
	}
}