com.xdev.jadoth.sqlengine.dbms.standard.StandardDMLAssembler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi Show documentation
Show all versions of xapi Show documentation
XDEV Application Framework
package com.xdev.jadoth.sqlengine.dbms.standard;
/*-
* #%L
* XDEV Application Framework
* %%
* Copyright (C) 2003 - 2020 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import static com.xdev.jadoth.sqlengine.SQL.LANG.DEFAULT_VALUES;
import static com.xdev.jadoth.sqlengine.SQL.LANG.DISTINCT;
import static com.xdev.jadoth.sqlengine.SQL.LANG.EXCEPT;
import static com.xdev.jadoth.sqlengine.SQL.LANG.FETCH;
import static com.xdev.jadoth.sqlengine.SQL.LANG.FIRST;
import static com.xdev.jadoth.sqlengine.SQL.LANG.FROM;
import static com.xdev.jadoth.sqlengine.SQL.LANG.INTERSECT;
import static com.xdev.jadoth.sqlengine.SQL.LANG.INTO;
import static com.xdev.jadoth.sqlengine.SQL.LANG.OFFSET;
import static com.xdev.jadoth.sqlengine.SQL.LANG.ONLY;
import static com.xdev.jadoth.sqlengine.SQL.LANG.ROW;
import static com.xdev.jadoth.sqlengine.SQL.LANG.ROWS;
import static com.xdev.jadoth.sqlengine.SQL.LANG.UNION;
import static com.xdev.jadoth.sqlengine.SQL.LANG.UNION_ALL;
import static com.xdev.jadoth.sqlengine.SQL.LANG._ON_;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.NEW_LINE;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation._;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.apo;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.blockCommentEnd;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.blockCommentStart;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.comma_;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.dot;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.n;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.par;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.qt;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.rap;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.selectItem_Comma_NEW_LINE;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.selectItem_NEW_LINE_Comma;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.singleLineComment;
import static com.xdev.jadoth.sqlengine.SQL.Punctuation.star;
import static com.xdev.jadoth.sqlengine.dbms.standard.StandardDbmsAdaptor.IDENTIFIER_DELIMITER;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.ASEXPRESSION;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.ESCAPE_DBL_QUOTES;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.ESCAPE_QUOTES;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.MINIINDENT;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.UNQUALIFIED;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.bitDelimitAliases;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.bitDelimitColumnIdentifiers;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.bitDelimitTableIdentifiers;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.indent;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.isOmitAlias;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.isPacked;
import static com.xdev.jadoth.sqlengine.internal.QueryPart.isSingleLine;
import static com.xdev.jadoth.sqlengine.internal.interfaces.TableExpression.Utils.getAlias;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import com.xdev.jadoth.sqlengine.DELETE;
import com.xdev.jadoth.sqlengine.INSERT;
import com.xdev.jadoth.sqlengine.SELECT;
import com.xdev.jadoth.sqlengine.SQL;
import com.xdev.jadoth.sqlengine.UPDATE;
import com.xdev.jadoth.sqlengine.dbms.DbmsAdaptor;
import com.xdev.jadoth.sqlengine.dbms.DbmsConfiguration;
import com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler;
import com.xdev.jadoth.sqlengine.dbms.DbmsSyntax;
import com.xdev.jadoth.sqlengine.exceptions.SQLEngineAssembleException;
import com.xdev.jadoth.sqlengine.interfaces.AssembableSqlExpression;
import com.xdev.jadoth.sqlengine.internal.AssignmentColumnsClause;
import com.xdev.jadoth.sqlengine.internal.AssignmentValuesClause;
import com.xdev.jadoth.sqlengine.internal.DoubleQuotedExpression;
import com.xdev.jadoth.sqlengine.internal.FROM;
import com.xdev.jadoth.sqlengine.internal.GROUP_BY;
import com.xdev.jadoth.sqlengine.internal.HAVING;
import com.xdev.jadoth.sqlengine.internal.JoinClause;
import com.xdev.jadoth.sqlengine.internal.ORDER_BY;
import com.xdev.jadoth.sqlengine.internal.QueryPart;
import com.xdev.jadoth.sqlengine.internal.QuotedExpression;
import com.xdev.jadoth.sqlengine.internal.SET;
import com.xdev.jadoth.sqlengine.internal.SqlClause;
import com.xdev.jadoth.sqlengine.internal.SqlColumn;
import com.xdev.jadoth.sqlengine.internal.SqlCondition;
import com.xdev.jadoth.sqlengine.internal.SqlDate;
import com.xdev.jadoth.sqlengine.internal.SqlExpression;
import com.xdev.jadoth.sqlengine.internal.SqlTime;
import com.xdev.jadoth.sqlengine.internal.SqlTimestamp;
import com.xdev.jadoth.sqlengine.internal.WHERE;
import com.xdev.jadoth.sqlengine.internal.interfaces.SelectItem;
import com.xdev.jadoth.sqlengine.internal.interfaces.TableExpression;
import com.xdev.jadoth.sqlengine.internal.tables.SqlTableIdentity;
import com.xdev.jadoth.sqlengine.types.Query;
import com.xdev.jadoth.sqlengine.types.TableQuery;
/**
* The Class StandardDMLAssembler.
*
* @param the generic type
*/
public class StandardDMLAssembler>
extends DbmsAdaptor.Member.Implementation
implements DbmsDMLAssembler
{
///////////////////////////////////////////////////////////////////////////
// constants //
/////////////////////
/** The Constant DATE. */
private static final String DATE = "yyyy-MM-dd";
/** The Constant TIME. */
private static final String TIME = "HH:mm:ss.SSSSSS";
/** The Constant TIMESTAMP. */
private static final String TIMESTAMP = DATE+" "+TIME;
/** The Constant date2TIMESTAMP. */
private static final SimpleDateFormat dateToTIMESTAMP = new SimpleDateFormat(TIMESTAMP);
/** The Constant date2DATE. */
private static final SimpleDateFormat dateToDATE = new SimpleDateFormat(DATE);
/** The Constant date2TIME. */
private static final SimpleDateFormat dateToTIME = new SimpleDateFormat(TIME);
/** The Constant __. */
protected static final String __ = " ";
/** The Constant _star. */
protected static final String _star = _+star;
/** The Constant OFFSET_. */
protected static final String OFFSET_ = OFFSET+_;
/** The Constant FETCH_FIRST_. */
protected static final String FETCH_FIRST_ = FETCH+_+FIRST+_;
/** The Constant _ROW. */
protected static final String _ROW = _+ROW;
/** The Constant _ROWS. */
protected static final String _ROWS = _+ROWS;
/** The Constant _ROW_ONLY. */
protected static final String _ROW_ONLY = _+ROW+_+ONLY;
/** The Constant _ROWS_ONLY. */
protected static final String _ROWS_ONLY = _+ROWS+_+ONLY;
/** The Constant _FROM_. */
protected static final String _FROM_ = _+FROM+_;
/** The Constant _INTO_. */
protected static final String _INTO_ = _+INTO+_;
///////////////////////////////////////////////////////////////////////////
// static methods //
/////////////////////
/**
* Gets the singleton standard dml assembler.
*
* @return the singleton standard dml assembler
*/
public static StandardDMLAssembler getSingletonStandardDMLAssembler(){
return StandardDbmsAdaptor.getSingletonStandardDbmsAdaptor().getDMLAssembler();
}
///////////////////////////////////////////////////////////////////////////
// constructors //
/////////////////////
/**
* Instantiates a new standard dml assembler.
*
* @param dbmsAdaptor the dbms adaptor
*/
public StandardDMLAssembler(final A dbmsAdaptor) {
super(dbmsAdaptor);
}
///////////////////////////////////////////////////////////////////////////
// getters //
/////////////////////
///////////////////////////////////////////////////////////////////////////
// setters //
/////////////////////
/**
* @param query
* @param sb
* @param indentLevel
* @param flags
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleQuery(Query, java.lang.StringBuilder, int, int)
*/
@Override
public void assembleQuery(
final Query query,
final StringBuilder sb,
final int indentLevel,
int flags
)
{
final boolean singleLineMode = isSingleLine(flags);
final String clauseSeperator = singleLineMode || isPacked(flags)?"":NEW_LINE;
final String newLine = singleLineMode?" ":NEW_LINE;
final DbmsConfiguration> config = this.getDbmsAdaptor().getConfiguration();
flags = flags
| bitDelimitTableIdentifiers(config.isDelimitTableIdentifiers())
| bitDelimitColumnIdentifiers(config.isDelimitColumnIdentifiers())
| bitDelimitAliases(config.isDelimitAliases())
;
this.assembleQueryName(query, sb, indentLevel, singleLineMode);
this.assembleQueryComment(query, sb, indentLevel, singleLineMode);
this.assembleQuerySubclassContext(query, sb, indentLevel, flags, clauseSeperator, newLine);
}
/**
* Assemble query name.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param singleLine the single line
* @return the string builder
*/
protected StringBuilder assembleQueryName(
final Query query, final StringBuilder sb, final int indentLevel, final boolean singleLine
)
{
final String name = query.getName();
if(name == null) return sb;
indent(sb, indentLevel, singleLine);
sb.append(singleLine?blockCommentStart:singleLineComment);
sb.append(name);
sb.append(singleLine?blockCommentEnd:NEW_LINE);
return sb;
}
/**
* Assemble query comment.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param singleLine the single line
* @return the string builder
*/
protected StringBuilder assembleQueryComment(
final Query query, final StringBuilder sb, final int indentLevel, final boolean singleLine
)
{
if(query.getComment() == null) return sb;
indent(sb, indentLevel, singleLine);
sb.append(blockCommentStart).append(singleLine?_:NEW_LINE);
this.assembleCommentLines(query, sb, indentLevel, singleLine);
sb.append(singleLine?_:NEW_LINE);
indent(sb, indentLevel, singleLine).append(blockCommentEnd);
sb.append(singleLine?_:NEW_LINE);
return sb;
}
/**
* Assemble comment lines.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param singleLine the single line
* @return the string builder
*/
protected StringBuilder assembleCommentLines(
final Query query, StringBuilder sb, final int indentLevel, final boolean singleLine
)
{
final String[] comments = query.getCommentLines();
if(comments == null){
return sb;
}
if(sb == null){
final String comment = query.getComment();
int commentLength = 0;
if(comment != null){
commentLength = comment.length();
}
else {
for(final String s : comments) {
if(s == null) break;
commentLength += s.length();
}
}
sb = new StringBuilder(commentLength);
}
final char seperator = singleLine?' ':n;
for(int i = 0; i < comments.length; i++) {
if(i > 0){
sb.append(seperator);
}
indent(sb, indentLevel, singleLine);
sb.append(comments[i]);
}
return sb;
}
/**
* Assemble query subclass context.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @return the string builder
* @return
*/
protected StringBuilder assembleQuerySubclassContext(
final Query query,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine
){
if(query instanceof SELECT){
return this.assembleSELECT(
(SELECT)query, sb, indentLevel, flags, clauseSeperator, newLine
);
}
else if(query instanceof INSERT){
return this.assembleINSERT(
(INSERT)query, sb, flags, clauseSeperator, newLine, indentLevel
);
}
else if(query instanceof UPDATE){
return this.assembleUPDATE(
(UPDATE)query, sb, indentLevel, flags, clauseSeperator, newLine
);
}
else if(query instanceof DELETE){
return this.assembleDELETE(
(DELETE)query, sb, flags, clauseSeperator, newLine, indentLevel
);
}
else {
throw new RuntimeException("Unhandled Query Type: "+query.getClass().getName());
}
}
/**
* Assemble select distinct.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleSelectDISTINCT(
final SELECT query,
final StringBuilder sb,
final int indentLevel,
final int flags
)
{
if(query.isDistinct()){
sb.append(_).append(DISTINCT);
}
return sb;
}
/**
* Assemble select items.
*
* @param query the query
* @param sb the sb
* @param flags the flags
* @param indentLevel the indent level
* @param newLine the new line
* @return the string builder
*/
protected StringBuilder assembleSelectItems(
final SELECT query,
final StringBuilder sb,
final int flags,
final int indentLevel,
final String newLine
)
{
final boolean singleLine = isSingleLine(flags);
final String indentItem = singleLine
?""
:indent(new StringBuilder(indentLevel), indentLevel, singleLine).append(__).toString()
;
final String itemSeperator = singleLine?comma_:SQL.config.list_CommaNewLine ?selectItem_Comma_NEW_LINE
:selectItem_NEW_LINE_Comma;
final List selectItems = query.getSelectItems();
if(selectItems == null || selectItems.isEmpty()){
if(query.getFromClause() != null){
sb.append(_star);
}
//otherwise, add no item at all
}
else{
sb.append(newLine).append(indentItem);
for(int i = 0, size = selectItems.size(); i < size; i++) {
if(i > 0){
sb.append(itemSeperator).append(indentItem);
}
// (27.08.2009 TM)XXX: CommaNewLine anschauen
// sb.append((SQL.config.list_CommaNewLine?" ":_));
this.assembleSelectItem(selectItems.get(i), sb, indentLevel, flags);
}
}
return sb;
}
/**
* @param selectItem
* @param sb
* @param indentLevel
* @param flags
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleSelectItem(com.xdev.jadoth.sqlengine.internal.interfaces.SelectItem, java.lang.StringBuilder, int, int)
*/
@Override
public void assembleSelectItem(
final SelectItem selectItem, final StringBuilder sb, final int indentLevel, final int flags
)
{
QueryPart.assembleObject(selectItem, this, sb, indentLevel, flags | MINIINDENT | ASEXPRESSION);
}
/**
* @param expression
* @param sb
* @param indentLevel
* @param flags
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleExpression(com.xdev.jadoth.sqlengine.internal.SqlExpression, java.lang.StringBuilder, int, int)
*/
@Override
public void assembleExpression(final SqlExpression expression, final StringBuilder sb, final int indentLevel, final int flags)
{
QueryPart.assembleObject(expression, this, sb, indentLevel, flags | MINIINDENT | ASEXPRESSION);
}
/**
* Assemble sql clause head.
*
* @param sqlClause the sql clause
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleSqlClauseHead(
final SqlClause> sqlClause,
final StringBuilder sb,
final int indentLevel,
final int flags
)
{
assembleKeyword: {
final String keyword = sqlClause.keyword();
if(keyword == null) break assembleKeyword;
// (12.11.2009 TM)XXX: Indentation BEFORE keyword check? (= always indent?)
indent(sb, indentLevel, isSingleLine(flags));
sb.append(keyword);
sb.append(isSingleLine(flags) ?_ :sqlClause.getKeyWordSeperator());
}
return sb;
}
/**
* Assemble sql clause body.
*
* @param sqlClause the sql clause
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleSqlClauseBody(
final SqlClause> sqlClause,
final StringBuilder sb,
final int indentLevel,
final int flags
)
{
final boolean singleLine = isSingleLine(flags);
final String bodySep = sqlClause.getBodyElementSeperator(singleLine);
final String indent = !singleLine && sqlClause.isIndentationAllowed()
?QueryPart.indent(new StringBuilder(indentLevel), indentLevel, singleLine).toString()
:""
;
if(sqlClause.isIndentFirstBodyElement()){
sb.append(indent);
}
boolean notEmpty = false;
for (final Object o : sqlClause) {
if(notEmpty){
sb.append(bodySep).append(indent);
}
else {
notEmpty = true;
}
if(o instanceof SqlExpression) {
this.assembleExpression((SqlExpression)o, sb, indentLevel, flags);
}
else {
QueryPart.assembleObject(o, this, sb, indentLevel, flags | MINIINDENT | ASEXPRESSION);
}
}
return sb;
}
/**
* Assemble parenthesized list clause body.
*
* @param sqlClause the sql clause
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleParenthesizedListClauseBody(
final SqlClause> sqlClause,
final StringBuilder sb,
final int indentLevel,
final int flags
)
{
indent(sb, indentLevel, isSingleLine(flags));
sb.append(par);
this.assembleSqlClauseBody(sqlClause, sb, indentLevel, flags);
sb.append(rap);
return sb;
}
/**
* Assemble sql clause.
*
* @param parentQuery the parent query
* @param sqlClause the sql clause
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
public StringBuilder assembleSqlClause(
// final TableQuery parentQuery,
final SqlClause> sqlClause,
final StringBuilder sb,
final int indentLevel,
final int flags
)
{
if(sqlClause == null) return sb;
/* (12.11.2009 TM)NOTE:
* Bad instanceof switch: assembleSqlClause() is supposed to avoid boiler plate code in calling context.
* But assemble() can't be moved back do SqlClause class itself because it's QueryAssembler-dependant.
*/
if(sqlClause instanceof FROM){
return this.assembleFROM(null, (FROM)sqlClause, sb, indentLevel, flags);
}
else if(sqlClause instanceof WHERE){
return this.assembleWHERE(null, (WHERE)sqlClause, sb, indentLevel, flags);
}
else if(sqlClause instanceof ORDER_BY){
return this.assembleORDERBY(null, (ORDER_BY)sqlClause, sb, indentLevel, flags);
}
else if(sqlClause instanceof GROUP_BY){
return this.assembleGROUPBY(null, (GROUP_BY)sqlClause, sb, indentLevel, flags);
}
else if(sqlClause instanceof HAVING){
return this.assembleHAVING(null, (HAVING)sqlClause, sb, indentLevel, flags);
}
else if(sqlClause instanceof JoinClause){
return this.assembleJOIN(null, (JoinClause)sqlClause, sb, indentLevel, flags);
}
else {
throw new SQLEngineAssembleException("Unhandled SqlClause: "+sqlClause);
}
}
/**
* Assemble from.
*
* @param parentQuery the parent query
* @param from the from
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleFROM(
final TableQuery parentQuery,
final FROM from,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(from, sb, indentLevel, flags);
// (27.08.2009 TM)TODO: von parent query holen
final String clauseSeperator = isSingleLine(flags) || isPacked(flags)?"":NEW_LINE;
final String lineSeperator = isSingleLine(flags)?" ":NEW_LINE;
final int passFlags = flags | ASEXPRESSION;
this.assembleTableExpression(from.getTable(), sb, indentLevel, passFlags);
final List joins = from.getJoins();
if(joins != null){
//joins is known to be an ArrayList
for(int i = 0, size = joins.size(); i < size; i++){
sb.append(lineSeperator).append(clauseSeperator);
this.assembleJOIN(parentQuery, joins.get(i), sb, indentLevel, passFlags);
// assembleObject(joins.get(i), this, sb, indentLevel, passFlags);
}
}
return sb;
}
protected StringBuilder assembleJOIN(
final TableQuery parentQuery,
final JoinClause join,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(join, sb, indentLevel, flags);
// (27.08.2009 TM)TODO: von parent query holen
final String lineSeperator = isSingleLine(flags)?" ":NEW_LINE;
final int passFlags = flags | ASEXPRESSION;
this.assembleTableExpression(join.getTable(), sb, indentLevel, passFlags);
sb.append(_ON_);
QueryPart.assembleObject(join.getJoinCondition(), this, sb, indentLevel, passFlags);
for(final SqlCondition sqlCondition : join) {
sb.append(lineSeperator);
QueryPart.assembleObject(sqlCondition, this, sb, indentLevel, passFlags);
}
return sb;
}
/**
* Assemble where.
*
* @param parentQuery the parent query
* @param where the where
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleWHERE(
final TableQuery parentQuery,
final WHERE where,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(where, sb, indentLevel, flags);
sb = this.assembleSqlClauseBody(where, sb, indentLevel, flags);
return sb;
}
/**
* Assemble groupby.
*
* @param parentQuery the parent query
* @param groupBy the group by
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleGROUPBY(
final TableQuery parentQuery,
final GROUP_BY groupBy,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(groupBy, sb, indentLevel, flags);
sb = this.assembleSqlClauseBody(groupBy, sb, indentLevel, flags);
return sb;
}
/**
* Assemble having.
*
* @param parentQuery the parent query
* @param having the having
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleHAVING(
final TableQuery parentQuery,
final HAVING having,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(having, sb, indentLevel, flags);
sb = this.assembleSqlClauseBody(having, sb, indentLevel, flags|ASEXPRESSION);
return sb;
}
/**
* Assemble orderby.
*
* @param parentQuery the parent query
* @param orderby the orderby
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleORDERBY(
final TableQuery parentQuery,
final ORDER_BY orderby,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(orderby, sb, indentLevel, flags);
sb = this.assembleSqlClauseBody(orderby, sb, indentLevel, flags);
return sb;
}
/**
* Assemble select row limit.
*
* @param query the query
* @param sb the sb
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @param indentLevel the indent level
* @return the string builder
*/
protected StringBuilder assembleSelectRowLimit(
final SELECT query,
final StringBuilder sb,
final int flags,
final String clauseSeperator,
final String newLine,
final int indentLevel
)
{
final Integer skip = query.getOffsetSkipCount();
final Integer range = query.getFetchFirstRowCount();
if(skip != null){
sb.append(newLine).append(clauseSeperator).append(OFFSET_).append(skip).append(skip==1?_ROW:_ROWS);
}
if(range != null){
sb.append(newLine);
if(skip != null){
sb.append(clauseSeperator);
}
sb.append(FETCH_FIRST_).append(range).append(range==1?_ROW_ONLY:_ROWS_ONLY);
}
return sb;
}
/**
* Assemble set.
*
* @param parentQuery the parent query
* @param set the set
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleSET(
final TableQuery parentQuery,
final SET set,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(set, sb, indentLevel, flags);
sb = this.assembleSqlClauseBody(set, sb, indentLevel, flags);
return sb;
}
/**
* Assemble assignment columns clause.
*
* @param parentQuery the parent query
* @param columns the columns
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleAssignmentColumnsClause(
final TableQuery parentQuery,
final AssignmentColumnsClause columns,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(columns, sb, indentLevel, flags);
sb = this.assembleParenthesizedListClauseBody(columns, sb, indentLevel, flags);
return sb;
}
/**
* Assemble assignment values clause.
*
* @param parentQuery the parent query
* @param values the values
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
*/
protected StringBuilder assembleAssignmentValuesClause(
final TableQuery parentQuery,
final AssignmentValuesClause values,
StringBuilder sb,
final int indentLevel,
final int flags
)
{
sb = this.assembleSqlClauseHead(values, sb, indentLevel, flags);
sb = this.assembleParenthesizedListClauseBody(values, sb, indentLevel, flags|ASEXPRESSION);
return sb;
}
/**
* Assemble select.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @return the string builder
* @return
*/
protected StringBuilder assembleSELECT(
final SELECT query,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine
)
{
indent(sb, indentLevel, isSingleLine(flags));
sb.append(query.keyword());
this.assembleSelectDISTINCT(query, sb, indentLevel, flags);
this.assembleSelectItems(query, sb, flags, indentLevel, newLine);
this.assembleSelectSqlClauses(query, sb, indentLevel, flags|ASEXPRESSION, clauseSeperator, newLine);
this.assembleSelectRowLimit(query, sb, flags, clauseSeperator, newLine, indentLevel);
this.assembleAppendSELECTs(query, sb, indentLevel, flags, clauseSeperator, newLine);
return sb;
}
/**
* Assemble append selec ts.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @return the string builder
*/
protected StringBuilder assembleAppendSELECTs(
final SELECT query,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine
)
{
SELECT appendSelect = query.getUnionSelect();
if(appendSelect != null) {
this.assembleAppendSelect(appendSelect, sb, indentLevel, flags, clauseSeperator, newLine, UNION);
return sb;
}
appendSelect = query.getUnionAllSelect();
if(appendSelect != null) {
this.assembleAppendSelect(appendSelect, sb, indentLevel, flags, clauseSeperator, newLine, UNION_ALL);
return sb;
}
appendSelect = query.getIntersectSelect();
if(appendSelect != null) {
this.assembleAppendSelect(appendSelect, sb, indentLevel, flags, clauseSeperator, newLine, INTERSECT);
return sb;
}
appendSelect = query.getExceptSelect();
if(appendSelect != null) {
this.assembleAppendSelect(appendSelect, sb, indentLevel, flags, clauseSeperator, newLine, EXCEPT);
return sb;
}
return sb;
}
/**
* Assemble append select.
*
* @param appendSelect the append select
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @param appendKeyword the append keyword
* @return the string builder
*/
protected StringBuilder assembleAppendSelect(
final SELECT appendSelect,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine,
final String appendKeyword
)
{
sb.append(clauseSeperator).append(newLine).append(appendKeyword).append(newLine).append(clauseSeperator);
QueryPart.assembleObject(appendSelect, this, sb, indentLevel, flags &~MINIINDENT &~ASEXPRESSION);
return sb;
}
public StringBuilder assembleObject(final Object object, final StringBuilder sb, final int indentLevel, final int flags)
{
if(object == null) {
sb.append((String)null);
}
else if(object instanceof AssembableSqlExpression){
((AssembableSqlExpression)object).assemble(this, sb, indentLevel, flags);
}
else {
this.assembleStringValue(object.toString(), sb, indentLevel, flags);
}
return sb;
}
/**
* Assemble select sql clauses.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @return the string builder
*/
protected StringBuilder assembleSelectSqlClauses(
final SELECT query,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine
)
{
for(final SqlClause> sqlClause : query.getSqlClauses()) {
if(sqlClause == null) continue;
sb.append(newLine).append(clauseSeperator);
this.assembleSqlClause(sqlClause, sb, indentLevel, flags);
}
return sb;
}
/**
* Assemble insert.
*
* @param query the query
* @param sb the sb
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @param indentLevel the indent level
* @return the string builder
* @return
*/
protected StringBuilder assembleINSERT(
final INSERT query,
final StringBuilder sb,
final int flags,
final String clauseSeperator,
final String newLine,
final int indentLevel
)
{
indent(sb, indentLevel, isSingleLine(flags)).append(query.keyword()).append(_INTO_);
this.assembleTableIdentifier(query.getTable(), sb, indentLevel, flags);
sb.append(newLine);
this.assembleAssignmentColumnsClause(query, query.getColumnsClause(), sb, indentLevel, flags|UNQUALIFIED);
sb.append(newLine);
final SELECT valueSelect = query.filterSelect();
if(valueSelect != null){
sb.append(clauseSeperator);
QueryPart.assembleObject(valueSelect, this, sb, indentLevel, flags);
}
else{
final AssignmentValuesClause values = query.getValuesClause();
if(values != null) {
this.assembleAssignmentValuesClause(query, values, sb, indentLevel, flags);
}
else{
indent(sb, indentLevel, isSingleLine(flags)).append(DEFAULT_VALUES);
}
}
return sb;
}
/**
* Assemble update.
*
* @param query the query
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @return the string builder
* @return
*/
protected StringBuilder assembleUPDATE(
final UPDATE query,
final StringBuilder sb,
final int indentLevel,
final int flags,
final String clauseSeperator,
final String newLine
)
{
indent(sb, indentLevel, isSingleLine(flags));
sb.append(query.keyword());
sb.append(_);
this.assembleTableIdentifier(query.getTable(), sb, indentLevel, flags);
final SET set = query.getSetClause();
sb.append(newLine);
this.assembleSET(query, set, sb, indentLevel, flags);
final FROM from = query.getFromClause();
if(from != null) {
sb.append(newLine).append(clauseSeperator);
this.assembleFROM(query, from, sb, indentLevel, flags);
}
final WHERE where = query.getWhereClause();
if(where != null){
sb.append(newLine).append(clauseSeperator);
this.assembleWHERE(query, where, sb, indentLevel, flags);
}
return sb;
}
/**
* Assemble delete.
*
* @param query the query
* @param sb the sb
* @param flags the flags
* @param clauseSeperator the clause seperator
* @param newLine the new line
* @param indentLevel the indent level
* @return the string builder
* @return
*/
protected StringBuilder assembleDELETE(
final DELETE query,
final StringBuilder sb,
final int flags,
final String clauseSeperator,
final String newLine,
final int indentLevel
)
{
//the first FROM is mandatory
indent(sb, indentLevel, isSingleLine(flags)).append(query.keyword()).append(_FROM_);
this.assembleTableIdentifier(query.getTable(), sb, indentLevel, flags);
final FROM from = query.getFromClause();
if(from != null) {
sb.append(newLine).append(clauseSeperator);
this.assembleFROM(query, from, sb, indentLevel, flags);
}
final WHERE where = query.getWhereClause();
if(where != null){
sb.append(newLine).append(clauseSeperator);
this.assembleWHERE(query, where, sb, indentLevel, flags);
}
return sb;
}
// (20.04.2010)XXX: Maybe decouple the two assembleQuotedExpression from assembleObject and move to SQLAssembler
/**
* Assemble double quoted expression.
*
* @param expression the expression
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleDoubleQuotedExpression(com.xdev.jadoth.sqlengine.internal.DoubleQuotedExpression, java.lang.StringBuilder, int, int)
*/
@Override
public StringBuilder assembleDoubleQuotedExpression(
final DoubleQuotedExpression expression, final StringBuilder sb, final int indentLevel, final int flags
)
{
// (13.10.2010 TM)TODO: assembleDoubleQuotedExpression() hotfix, consolidate
final Object expressionObject = expression.getExpressionObject();
if(expressionObject == null){
return sb.append((String)null);
}
sb.append(qt);
QueryPart.assembleObject(expressionObject, this, sb, indentLevel, flags | ESCAPE_DBL_QUOTES);
sb.append(qt);
return sb;
}
/**
* Assemble quoted expression.
*
* @param expression the expression
* @param sb the sb
* @param indentLevel the indent level
* @param flags the flags
* @return the string builder
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleQuotedExpression(com.xdev.jadoth.sqlengine.internal.QuotedExpression, java.lang.StringBuilder, int, int)
*/
@Override
public StringBuilder assembleQuotedExpression(
final QuotedExpression expression, final StringBuilder sb, final int indentLevel, final int flags
)
{
// (13.10.2010 TM)TODO: assembleQuotedExpression() hotfix, consolidate
final Object expressionObject = expression.getExpressionObject();
if(expressionObject == null){
return sb.append((String)null);
}
sb.append(apo);
QueryPart.assembleObject(expressionObject, this, sb, indentLevel, flags | ESCAPE_QUOTES);
sb.append(apo);
return sb;
}
///////////////////////////////////////////////////////////////////////////
// override methods //
/////////////////////
/**
* @return
*/
@Override
public DateFormat getDateFormatDATE()
{
return dateToDATE;
}
/**
* @return
*/
@Override
public DateFormat getDateFormatTIME()
{
return dateToTIME;
}
/**
* @return
*/
@Override
public DateFormat getDateFormatTIMESTAMP()
{
return dateToTIMESTAMP;
}
@Override
public StringBuilder assembleDateTimeExpression(final SqlTimestamp dateTimeExpression, final StringBuilder sb)
{
sb.append(
dateTimeExpression instanceof SqlDate ?SQL.LANG.DATE
:dateTimeExpression instanceof SqlTime ?SQL.LANG.TIME
:SQL.LANG.TIMESTAMP
)
.append(_).append(apo)
.append(dateTimeExpression.getDateFormat(this).format(dateTimeExpression.getDate()))
.append(apo)
;
return sb;
}
/**
* @param column
* @param sb
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleColumnQualifier(com.xdev.jadoth.sqlengine.internal.SqlColumn, java.lang.StringBuilder, int)
*/
@Override
public StringBuilder assembleColumnQualifier(final SqlColumn column, final StringBuilder sb, final int flags)
{
final TableExpression owner = column.getOwner();
String qualifier = getAlias(owner);
if(qualifier == null || QueryPart.isQualifyByTable(flags)){
qualifier = owner.toString();
}
return sb.append(qualifier).append(dot);
}
/**
* @param column
* @param sb
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleColumn(com.xdev.jadoth.sqlengine.internal.SqlColumn, java.lang.StringBuilder, int)
*/
@Override
public StringBuilder assembleColumn(
final SqlColumn column, final StringBuilder sb, final int indentLevel, int flags
)
{
final TableExpression owner = column.getOwner();
final DbmsAdaptor> dbms = this.getDbmsAdaptor();
final boolean delimColumn = dbms.getConfiguration().isDelimitColumnIdentifiers()
|| QueryPart.isDelimitColumnIdentifiers(flags)
;
final char delim = dbms.getIdentifierDelimiter();
flags |= QueryPart.bitDelimitColumnIdentifiers(
this.getDbmsAdaptor().getConfiguration().isDelimitColumnIdentifiers()
);
if(delimColumn){
sb.append(delim);
}
if(owner != null && !QueryPart.isUnqualified(flags)) {
this.assembleColumnQualifier(column, sb, flags);
}
QueryPart.assembleObject(column.getExpressionObject(), this, sb, indentLevel, flags);
if(delimColumn){
sb.append(delim);
}
return sb;
}
/**
* @param identifier
* @param sb
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleDelimitedIdentifier(java.lang.String, java.lang.StringBuilder, int)
*/
@Override
public StringBuilder assembleDelimitedIdentifier(final String identifier, final StringBuilder sb, final int flags)
{
return sb.append(IDENTIFIER_DELIMITER).append(identifier).append(IDENTIFIER_DELIMITER);
}
/**
* @param object
* @param sb
* @param indentLevel
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleObject(java.lang.Object, java.lang.StringBuilder, int, int)
*/
@Override
public StringBuilder assembleStringValue(final String s, final StringBuilder sb, final int indentLevel, final int flags)
{
final DbmsAdaptor> dbms = this.getDbmsAdaptor();
if(dbms.getConfiguration().isAutoEscapeReservedWords() && dbms.getSyntax().isReservedWord(s)){
final char d = dbms.getIdentifierDelimiter();
sb.append(d).append(s).append(d);
return sb;
}
final int length = s.length();
final char[] chars = new char[length];
s.getChars(0, length, chars, 0);
sb.ensureCapacity(sb.length() + length + 10);
if (QueryPart.isEscapeQuotes(flags)) {
for(final char c : chars){
if(c == apo) {
sb.append(apo);
}
sb.append(c);
}
}
else if (QueryPart.isEscapeDoubleQuotes(flags)) {
for(final char c : chars){
if(c == qt) {
sb.append(qt);
}
sb.append(c);
}
}
else {
sb.append(s);
}
return sb;
}
/**
* @param tableExpression
* @param sb
* @param indentLevel
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleTableExpression(com.xdev.jadoth.sqlengine.internal.interfaces.TableExpression, java.lang.StringBuilder, int, int)
*/
@Override
public StringBuilder assembleTableExpression(
final TableExpression tableExpression, final StringBuilder sb, final int indentLevel, final int flags
)
{
if(tableExpression instanceof SqlTableIdentity){
return this.assembleTableIdentifier((SqlTableIdentity)tableExpression, sb, indentLevel, flags);
}
QueryPart.assembleObject(tableExpression, this, sb, indentLevel, flags);
if(!isOmitAlias(flags)){
final String alias = TableExpression.Utils.getAlias(tableExpression);
if(alias != null) {
sb.append(_);
sb.append(alias);
}
}
return sb;
}
/**
* @param table
* @param sb
* @param indentLevel
* @param flags
* @return
* @see com.xdev.jadoth.sqlengine.dbms.DbmsDMLAssembler#assembleTableIdentifier(com.xdev.jadoth.sqlengine.internal.tables.SqlTableIdentity, java.lang.StringBuilder, int, int)
*/
@Override
public StringBuilder assembleTableIdentifier(
final SqlTableIdentity table, final StringBuilder sb, final int indentLevel, final int flags
)
{
final DbmsAdaptor> dbms = this.getDbmsAdaptor();
final DbmsSyntax> syntax = dbms.getSyntax();
final DbmsConfiguration> config = dbms.getConfiguration();
final char delim = dbms.getIdentifierDelimiter();
final SqlTableIdentity.Sql sql = table.sql();
final String schema = sql.schema;
final String name = sql.name;
final boolean delimTable = QueryPart.isDelimitTableIdentifiers(flags)
|| config.isDelimitTableIdentifiers()
|| config.isAutoEscapeReservedWords()
&&
(syntax.isReservedWord(name) || schema != null && syntax.isReservedWord(schema))
;
if(delimTable){
sb.append(delim);
}
if(schema != null){
sb.append(schema).append(dot);
}
sb.append(name);
if(delimTable){
sb.append(delim);
}
if(!isOmitAlias(flags)){
final String alias = sql.alias;
if(alias != null && alias.length() > 0){
sb.append(_);
if(config.isDelimitAliases() || config.isAutoEscapeReservedWords() && syntax.isReservedWord(alias)){
sb.append(delim).append(alias).append(delim);
}
else {
sb.append(alias);
}
}
}
return sb;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy