DB2QueryObject.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.sql;

  21. import java.text.SimpleDateFormat;
  22. import java.util.Date;
  23. import java.util.Iterator;

  24. import org.openspcoop2.utils.TipiDatabase;
  25. import org.openspcoop2.utils.date.DateUtils;

  26. /**
  27.  * SQLServerQueryObject
  28.  *
  29.  *
  30.  * @author Poli Andrea (apoli@link.it)
  31.  * @author $Author$
  32.  * @version $Rev$, $Date$
  33.  */
  34. public class DB2QueryObject extends SQLQueryObjectCore {

  35.     public DB2QueryObject(TipiDatabase tipoDatabase) {
  36.         super(tipoDatabase);
  37.     }
  38.    
  39.    
  40.     @Override
  41.     protected String getPrefixCastValue(CastColumnType type, int length) {
  42.         switch (type) {
  43.         case INT:
  44.         case LONG:
  45.         case STRING:
  46.         case TIMESTAMP:
  47.             return "CAST( ";
  48.         case NONE:
  49.             return "";
  50.         }
  51.         return "";
  52.     }
  53.     @Override
  54.     protected String getSuffixCastValue(CastColumnType type, int length) {
  55.         StringBuilder sb = new StringBuilder();
  56.         sb.append(" AS ");
  57.         switch (type) {
  58.         case INT:
  59.             sb.append("INT");
  60.             break;
  61.         case LONG:
  62.             sb.append("BIGINT");
  63.             break;
  64.         case STRING:
  65.             sb.append("VARCHAR");
  66.             break;
  67.         case TIMESTAMP:
  68.             sb.append("TIMESTAMP");
  69.             break;
  70.         case NONE:
  71.             return "";
  72.         }
  73.         sb.append(")");
  74.         return sb.toString();
  75.     }
  76.    
  77.    

  78.    
  79.     /**
  80.      * Ritorna una costante  di tipo 'timestamp'
  81.      *
  82.      * @param date Costante
  83.      */
  84.     @Override
  85.     public String getSelectTimestampConstantField(Date date) throws SQLQueryObjectException{
  86.         SimpleDateFormat sqlDateformat = DateUtils.getDefaultDateTimeFormatter("yyyy-MM-dd HH:mm:ss.SSS");
  87.         return "TIMESTAMP('"+sqlDateformat.format(date)+"', 'YYYY-MM-DD HH24:MI:SS.FF3')";
  88.     }
  89.    
  90.    
  91.    
  92.     @Override
  93.     public String getUnixTimestampConversion(String column){
  94.         return "((((CAST (DAYS("+column+"-CURRENT_TIMEZONE) - DAYS('1970-01-01') AS BIGINT)*86400)+MIDNIGHT_SECONDS("+
  95.                 column+"-CURRENT_TIMEZONE))*1000)+(MICROSECOND("+
  96.                 column+")/1000))";
  97.     }
  98.    
  99.     @Override
  100.     public String getDiffUnixTimestamp(String columnMax,String columnMin){
  101.         return "( "+getUnixTimestampConversion(columnMax)+" - "+getUnixTimestampConversion(columnMin)+" )";
  102.     }
  103.    
  104.    
  105.    


  106.     @Override
  107.     public ISQLQueryObject addSelectAvgTimestampField(String field,
  108.             String alias) throws SQLQueryObjectException {
  109.         if(field==null)
  110.             throw new SQLQueryObjectException(SQLQueryObjectCore.FIELD_DEVE_ESSERE_DIVERSO_NULL);
  111.         // Trasformo in UNIX_TIMESTAMP
  112.         String fieldSQL = "avg("+this.getUnixTimestampConversion(field)+")";
  113.         if(alias != null){
  114.             /**fieldSQL = fieldSQL + " as "+alias;*/
  115.             fieldSQL = fieldSQL + this.getDefaultAliasFieldKeyword() + alias;
  116.         }
  117.         this.engineAddSelectField(null,fieldSQL,null,false,true);
  118.         this.fieldNames.add(alias);
  119.         return this;
  120.     }


  121.     @Override
  122.     public ISQLQueryObject addSelectMaxTimestampField(String field, String alias)
  123.             throws SQLQueryObjectException {
  124.         if(field==null)
  125.             throw new SQLQueryObjectException(SQLQueryObjectCore.FIELD_DEVE_ESSERE_DIVERSO_NULL);
  126.         // Trasformo in UNIX_TIMESTAMP
  127.         String fieldSQL = "max("+this.getUnixTimestampConversion(field)+")";
  128.         if(alias != null){
  129.             /**fieldSQL = fieldSQL + " as "+alias;*/
  130.             fieldSQL = fieldSQL + this.getDefaultAliasFieldKeyword() + alias;
  131.         }
  132.         this.engineAddSelectField(null,fieldSQL,null,false,true);
  133.         this.fieldNames.add(alias);
  134.         return this;
  135.     }


  136.     @Override
  137.     public ISQLQueryObject addSelectMinTimestampField(String field, String alias)
  138.             throws SQLQueryObjectException {
  139.         if(field==null)
  140.             throw new SQLQueryObjectException(SQLQueryObjectCore.FIELD_DEVE_ESSERE_DIVERSO_NULL);
  141.         // Trasformo in UNIX_TIMESTAMP
  142.         String fieldSQL = "min("+this.getUnixTimestampConversion(field)+")";
  143.         if(alias != null){
  144.             /**fieldSQL = fieldSQL + " as "+alias;*/
  145.             fieldSQL = fieldSQL + this.getDefaultAliasFieldKeyword() + alias;
  146.         }
  147.         this.engineAddSelectField(null,fieldSQL,null,false,true);
  148.         this.fieldNames.add(alias);
  149.         return this;
  150.     }


  151.     @Override
  152.     public ISQLQueryObject addSelectSumTimestampField(String field, String alias)
  153.             throws SQLQueryObjectException {
  154.         if(field==null)
  155.             throw new SQLQueryObjectException(SQLQueryObjectCore.FIELD_DEVE_ESSERE_DIVERSO_NULL);
  156.         // Trasformo in UNIX_TIMESTAMP
  157.         String fieldSQL = "sum("+this.getUnixTimestampConversion(field)+")";
  158.         if(alias != null){
  159.             /**fieldSQL = fieldSQL + " as "+alias;*/
  160.             fieldSQL = fieldSQL + this.getDefaultAliasFieldKeyword() + alias;
  161.         }
  162.         this.engineAddSelectField(null,fieldSQL,null,false,true);
  163.         this.fieldNames.add(alias);
  164.         return this;
  165.     }





  166.     @Override
  167.     public ISQLQueryObject addFromTable(ISQLQueryObject subSelect)
  168.             throws SQLQueryObjectException {
  169.         StringBuilder bf = new StringBuilder();
  170.         bf.append(" ( ");
  171.         bf.append(subSelect.createSQLQuery());
  172.         bf.append(" ) ");
  173.         // Devo forzare l'utilizzo di un alias su una sottoselct dentro il FROM
  174.         // Genero Tre caratteri alafabetici casuali per dare un alias del tipo "tabellaXXX"
  175.         StringBuilder subselectalias = new StringBuilder();
  176.         subselectalias.append("tabella");
  177.         int rnd;
  178.         char base;
  179.         for (int count=0 ; count < 3; count++ ){
  180.             rnd = (SQLQueryObjectCore.getRandom().nextInt(52) );
  181.             base = (rnd < 26) ? 'A' : 'a';
  182.             subselectalias.append((char) (base + rnd % 26));            
  183.         }
  184.         this.addFromTable(bf.toString(),subselectalias.toString());
  185.         return this;
  186.     }



  187.     @Override
  188.     protected EscapeSQLConfiguration getEscapeSQLConfiguration(){
  189.        
  190.         EscapeSQLConfiguration config = new EscapeSQLConfiguration();
  191.         config.addCharacter('_');
  192.         config.addCharacter('%');
  193.         config.addCharacter('\\');
  194.         config.setUseEscapeClausole(true);
  195.         config.setEscape('\\');
  196.        
  197.         // special
  198.         config.addCharacterWithOtherEscapeChar('\'','\'');
  199.        
  200.         return config;
  201.     }


  202.    
  203.    
  204.    
  205.    
  206.    
  207.    
  208.    
  209.     private static final String DAY_FORMAT_FULL_DAY_NAME = "%A";
  210.     private static final String DAY_FORMAT_SHORT_DAY_NAME = "%a";
  211.    
  212.     private SQLQueryObjectException newSQLQueryObjectExceptionDayFormatEnum(DayFormatEnum dayFormat) {
  213.         return new SQLQueryObjectException("DayFormatEnum '"+dayFormat+"' unknown");
  214.     }
  215.     @Override
  216.     protected String getDayFormat(DayFormatEnum dayFormat) throws SQLQueryObjectException {
  217.         switch (dayFormat) {
  218.         case FULL_DAY_NAME:
  219.             return DAY_FORMAT_FULL_DAY_NAME;
  220.         case SHORT_DAY_NAME:
  221.             return DAY_FORMAT_SHORT_DAY_NAME;
  222.         default:
  223.         }
  224.         throw newSQLQueryObjectExceptionDayFormatEnum(dayFormat);
  225.     }
  226.     @Override
  227.     public String getExtractDayFormatFromTimestampFieldPrefix(DayFormatEnum dayFormat) throws SQLQueryObjectException {
  228.         if(dayFormat==null) {
  229.             throw new SQLQueryObjectException("dayFormat undefined");
  230.         }
  231.         switch (dayFormat) {
  232.         case FULL_DAY_NAME:
  233.         case SHORT_DAY_NAME:
  234.             return super.getExtractDayFormatFromTimestampFieldPrefix(dayFormat);
  235.         case DAY_OF_YEAR:
  236.             return "DAYOFYEAR(";
  237.         case DAY_OF_WEEK:
  238.             return "DAYOFWEEK(";
  239.         }
  240.         throw newSQLQueryObjectExceptionDayFormatEnum(dayFormat);
  241.     }
  242.     @Override
  243.     public String getExtractDayFormatFromTimestampFieldSuffix(DayFormatEnum dayFormat) throws SQLQueryObjectException {
  244.         if(dayFormat==null) {
  245.             throw new SQLQueryObjectException("dayFormat undefined");
  246.         }
  247.         switch (dayFormat) {
  248.         case FULL_DAY_NAME:
  249.         case SHORT_DAY_NAME:
  250.             return super.getExtractDayFormatFromTimestampFieldSuffix(dayFormat);
  251.         case DAY_OF_YEAR:
  252.         case DAY_OF_WEEK:
  253.             return ")";
  254.         }
  255.         throw newSQLQueryObjectExceptionDayFormatEnum(dayFormat);
  256.     }
  257.    
  258.    
  259.    
  260.    
  261.    
  262.    


  263.     @Override
  264.     public String createSQLQuery() throws SQLQueryObjectException{
  265.         return this.createSQLQuery(false);
  266.     }
  267.     private String createSQLQuery(boolean union) throws SQLQueryObjectException{
  268.        
  269.         this.precheckBuildQuery();
  270.        
  271.         StringBuilder bf = new StringBuilder();

  272.         bf.append("SELECT ");

  273.         if(this.isSelectDistinct())
  274.             bf.append(" DISTINCT ");

  275.         // forzatura di indici
  276.         if( !(this.offset>=0 || this.limit>=0) ){
  277.             Iterator<String> itForceIndex = this.forceIndexTableNames.iterator();
  278.             while(itForceIndex.hasNext()){
  279.                 bf.append(" "+itForceIndex.next()+" ");
  280.             }
  281.         }

  282.         // select field
  283.         addSQLQuerySelectField(bf);

  284.         bf.append(getSQL(false,false,false,union));

  285.         /**if( this.offset>=0 || this.limit>=0)
  286.         //  System.out.println("SQL ["+bf.toString()+"]");*/

  287.         // Limit (senza offset)
  288.         if(this.offset<0 && this.limit>0){
  289.             bf.append(" FETCH FIRST ");
  290.             bf.append(this.limit);
  291.             bf.append(" ROWS ONLY ");
  292.         }

  293.         return bf.toString();
  294.     }
  295.     private void addSQLQuerySelectField(StringBuilder bf) {
  296.         if(this.fields.isEmpty()){
  297.             bf.append("*");
  298.         }else{
  299.             Iterator<String> it = this.fields.iterator();
  300.             boolean first = true;
  301.             while(it.hasNext()){
  302.                 if(!first)
  303.                     bf.append(",");
  304.                 else
  305.                     first = false;

  306.                 String field = it.next();
  307.                 if( this.offset>=0 ){

  308.                     field = this.normalizeField(field,false);

  309.                 }
  310.                 bf.append(field);
  311.             }
  312.         }
  313.     }





  314.     @Override
  315.     public String createSQLDeleteEngine() throws SQLQueryObjectException {

  316.         StringBuilder bf = new StringBuilder();

  317.         bf.append("DELETE ");

  318.         bf.append(getSQL(true,false,false,false));
  319.         return bf.toString();
  320.     }





  321.     private String getSQL(boolean delete,boolean update,boolean conditions,boolean union) throws SQLQueryObjectException {  
  322.         StringBuilder bf = new StringBuilder();

  323.         if(this.selectForUpdate){
  324.             this.checkSelectForUpdate(update, delete, union);
  325.         }
  326.        
  327.         if(!update && !conditions){
  328.                        
  329.             // From
  330.             bf.append(SQLQueryObjectCore.FROM_SEPARATOR);


  331.             // Se e' presente Offset o Limit
  332.             /**if( (this.offset>=0 || this.limit>=0) && (delete==false)) {*/
  333.             // Rilascio vincolo di order by in caso di limit impostato.
  334.             // Il vincolo rimane per l'offset, per gestire le select annidate di qualche implementazioni come Oracle,SQLServer ...
  335.             if( (this.offset>=0) && (!delete)){

  336.                 /**java.util.List<String> aliasOrderByDistinct = new java.util.ArrayList<>();*/

  337.                 /**if(this.isSelectDistinct()==false)*/        
  338.                 bf.append(SQLQueryObjectCore.SELECT_SEPARATOR_CON_INIZIO_APERTURA);
  339.                 /**else
  340.                 //  bf.append(" ( SELECT DISTINCT ");*/

  341.                 // Questa istruzione ci vuole altrimenti in presenza di order by, group by si ottiene il seguente errore:
  342.                 // The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
  343.                 // In questo segmento di select forse non server?
  344.                 /** bf.append("TOP 100 PERCENT "); */

  345.                 Iterator<String> itForceIndex = this.forceIndexTableNames.iterator();
  346.                 while(itForceIndex.hasNext()){
  347.                     bf.append(" "+itForceIndex.next()+" ");
  348.                 }

  349.                 if(this.isSelectDistinct()){
  350.                     if(this.fields.isEmpty()){
  351.                         Iterator<String> it = this.tableNames.iterator();
  352.                         boolean first = true;
  353.                         while(it.hasNext()){
  354.                             if(!first)
  355.                                 bf.append(",");
  356.                             else
  357.                                 first = false;
  358.                             String t = it.next();
  359.                             bf.append(t+".*");
  360.                         }
  361.                     }else{
  362.                         Iterator<String> it = this.fields.iterator();
  363.                         boolean first = true;
  364.                         while(it.hasNext()){
  365.                             if(!first)
  366.                                 bf.append(",");
  367.                             else
  368.                                 first = false;

  369.                             String field = it.next();
  370.                             if( this.offset>=0 ){

  371.                                 field = this.normalizeField(field,false);

  372.                             }
  373.                             bf.append(field);
  374.                         }
  375.                     }
  376.                 }
  377.                 else{
  378.                     if(this.fields.isEmpty()){
  379.                         Iterator<String> it = this.tableNames.iterator();
  380.                         boolean first = true;
  381.                         while(it.hasNext()){
  382.                             if(!first)
  383.                                 bf.append(",");
  384.                             else
  385.                                 first = false;
  386.                             String t = it.next();
  387.                             bf.append(t+".*");
  388.                         }
  389.                     }else{
  390.                         Iterator<String> it = this.fields.iterator();
  391.                         boolean first = true;
  392.                         while(it.hasNext()){
  393.                             if(!first)
  394.                                 bf.append(",");
  395.                             else
  396.                                 first = false;
  397.                             String f = it.next();
  398.                             bf.append(f);
  399.                         }
  400.                     }
  401.                 }


  402.                 bf.append(" , ROW_NUMBER() OVER ( ORDER BY ");

  403.                 // Condizione OrderBy
  404.                 if(this.orderBy.isEmpty()){
  405.                     throw new SQLQueryObjectException(SQLQueryObjectCore.CONDIZIONI_ORDER_BY_RICHESTE);
  406.                 }
  407.                 if(!this.orderBy.isEmpty()){
  408.                     Iterator<String> it = this.orderBy.iterator();
  409.                     boolean first = true;
  410.                     while(it.hasNext()){
  411.                         if(!first)
  412.                             bf.append(",");
  413.                         else
  414.                             first = false;
  415.                         String condizione = it.next();
  416.                         /**System.out.println("=======================");
  417.                         System.out.println("alias: "+this.alias);
  418.                         System.out.println("condizione: "+condizione);
  419.                         System.out.println("KEY: "+(this.alias.containsKey(condizione)));
  420.                         System.out.println("VALUE: "+(this.alias.containsValue(condizione)));
  421.                         System.out.println("DISTINCT: "+(this.isSelectDistinct()));
  422.                         System.out.println("=======================");*/
  423.                         if(this.alias.containsKey(condizione)){
  424.                             if(this.isSelectDistinct()){
  425.                                 bf.append(condizione);
  426.                             }
  427.                             else{
  428.                                 bf.append(this.alias.get(condizione));
  429.                             }
  430.                         }else if(this.alias.containsValue(condizione)) {
  431.                             bf.append(condizione);
  432.                         }
  433.                         else{
  434.                             bf.append(this.normalizeField(condizione));
  435.                         }
  436.                         boolean sortTypeAsc = this.sortTypeAsc;
  437.                         if(this.orderBySortType.containsKey(condizione)){
  438.                             sortTypeAsc = this.orderBySortType.get(condizione);
  439.                         }
  440.                         if(sortTypeAsc){
  441.                             bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  442.                         }else{
  443.                             bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  444.                         }
  445.                     }
  446.                 }

  447.                 bf.append(" ) AS rowNumber ");


  448.                 bf.append(SQLQueryObjectCore.FROM_SEPARATOR);

  449.                 if(this.isSelectDistinct()){

  450.                     bf.append(" ( SELECT DISTINCT ");

  451.                     if(this.fields.isEmpty()){
  452.                         Iterator<String> it = this.tableNames.iterator();
  453.                         boolean first = true;
  454.                         while(it.hasNext()){
  455.                             if(!first)
  456.                                 bf.append(",");
  457.                             else
  458.                                 first = false;
  459.                             String t = it.next();
  460.                             bf.append(t+".*");
  461.                         }
  462.                     }else{
  463.                         Iterator<String> it = this.fields.iterator();
  464.                         boolean first = true;
  465.                         while(it.hasNext()){
  466.                             if(!first)
  467.                                 bf.append(",");
  468.                             else
  469.                                 first = false;
  470.                             String f = it.next();
  471.                             bf.append(f);
  472.                         }
  473.                     }

  474.                     bf.append(SQLQueryObjectCore.FROM_SEPARATOR);
  475.                 }


  476.                 // Table dove effettuare la ricerca 'FromTable'
  477.                 if(this.tables.isEmpty()){
  478.                     throw new SQLQueryObjectException(SQLQueryObjectCore.TABELLA_RICERCA_FROM_NON_DEFINITA);
  479.                 }else{
  480.                     Iterator<String> it = this.tables.iterator();
  481.                     boolean first = true;
  482.                     while(it.hasNext()){
  483.                         if(!first)
  484.                             bf.append(",");
  485.                         else
  486.                             first = false;
  487.                         bf.append(it.next());
  488.                     }
  489.                 }

  490.                 // Condizioni di Where
  491.                 if(!this.conditions.isEmpty()){

  492.                     bf.append(SQLQueryObjectCore.WHERE_SEPARATOR);

  493.                     if(this.notBeforeConditions){
  494.                         bf.append(SQLQueryObjectCore.NOT_SEPARATOR_APERTURA);
  495.                     }

  496.                     for(int i=0; i<this.conditions.size(); i++){

  497.                         if(i>0){
  498.                             if(this.andLogicOperator){
  499.                                 bf.append(SQLQueryObjectCore.AND_SEPARATOR);
  500.                             }else{
  501.                                 bf.append(SQLQueryObjectCore.OR_SEPARATOR);
  502.                             }
  503.                         }
  504.                         String cond = this.conditions.get(i);              
  505.                         bf.append(cond);
  506.                     }

  507.                     if(this.notBeforeConditions){
  508.                         bf.append(" )");
  509.                     }
  510.                 }

  511.                 // Condizione GroupBy
  512.                 if((!this.getGroupByConditions().isEmpty()) && (!delete)){
  513.                     bf.append(SQLQueryObjectCore.GROUP_BY_SEPARATOR);
  514.                     Iterator<String> it = this.getGroupByConditions().iterator();
  515.                     boolean first = true;
  516.                     while(it.hasNext()){
  517.                         if(!first)
  518.                             bf.append(",");
  519.                         else
  520.                             first = false;
  521.                         bf.append(it.next());
  522.                     }
  523.                 }


  524.                 if(this.isSelectDistinct()){

  525.                     // Order solo in presenza di select distinct
  526.                     if((!this.orderBy.isEmpty()) && (!delete)){
  527.                         bf.append(SQLQueryObjectCore.ORDER_BY_SEPARATOR);
  528.                         Iterator<String> it = this.orderBy.iterator();
  529.                         boolean first = true;
  530.                         while(it.hasNext()){
  531.                             String column = it.next();
  532.                             if(!first)
  533.                                 bf.append(",");
  534.                             else
  535.                                 first = false;
  536.                             bf.append(column);
  537.                             boolean sortTypeAsc = this.sortTypeAsc;
  538.                             if(this.orderBySortType.containsKey(column)){
  539.                                 sortTypeAsc = this.orderBySortType.get(column);
  540.                             }
  541.                             if(sortTypeAsc){
  542.                                 bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  543.                             }else{
  544.                                 bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  545.                             }
  546.                         }
  547.                     }

  548.                     // Devo forzare l'utilizzo di un alias su una sottoselct dentro il FROM        
  549.                     bf.append(" ) ");
  550.                     bf.append(this.getDefaultAliasFieldKeyword());
  551.                     bf.append("tableSelectRaw");
  552.                     // Genero Tre caratteri alfabetici casuali per dare un alias del tipo "tabellaXXX"
  553.                     int rnd;
  554.                     char base;
  555.                     for (int count=0 ; count < 3; count++ ){
  556.                         rnd = (SQLQueryObjectCore.getRandom().nextInt(52) );
  557.                         base = (rnd < 26) ? 'A' : 'a';
  558.                         bf.append((char) (base + rnd % 26));

  559.                     }
  560.                 }


  561.                 // Devo forzare l'utilizzo di un alias su una sottoselct dentro il FROM        
  562.                 bf.append(" ) ");
  563.                 bf.append(this.getDefaultAliasFieldKeyword());
  564.                 bf.append("tabella");
  565.                 // Genero Tre caratteri alfabetici casuali per dare un alias del tipo "tabellaXXX"
  566.                 int rnd;
  567.                 char base;
  568.                 for (int count=0 ; count < 3; count++ ){
  569.                     rnd = (SQLQueryObjectCore.getRandom().nextInt(52) );
  570.                     base = (rnd < 26) ? 'A' : 'a';
  571.                     bf.append((char) (base + rnd % 26));

  572.                 }
  573.                 bf.append(" WHERE ( ");

  574.                 if(this.offset>=0){
  575.                     bf.append(" rowNumber > ");
  576.                     bf.append(this.offset);
  577.                 }
  578.                 if(this.limit>=0){
  579.                     if(this.offset>=0)
  580.                         bf.append(" AND");
  581.                     bf.append(" rowNumber <=  ");
  582.                     if(this.offset>=0)
  583.                         bf.append(this.offset+this.limit);
  584.                     else
  585.                         bf.append(this.limit);
  586.                 }
  587.                 bf.append(" )");


  588.                 // ORDER BY FINALE
  589.                 if(!union &&
  590.                     (!this.orderBy.isEmpty())
  591.                     ){
  592.                     bf.append(SQLQueryObjectCore.ORDER_BY_SEPARATOR);
  593.                     Iterator<String> it = this.orderBy.iterator();
  594.                     boolean first = true;
  595.                     while(it.hasNext()){
  596.                         if(!first)
  597.                             bf.append(",");
  598.                         else
  599.                             first = false;
  600.                         String field = it.next();
  601.                        
  602.                         bf.append(this.normalizeField(field));  
  603.                    
  604.                         boolean sortTypeAsc = this.sortTypeAsc;
  605.                         if(this.orderBySortType.containsKey(field)){
  606.                             sortTypeAsc = this.orderBySortType.get(field);
  607.                         }
  608.                         if(sortTypeAsc){
  609.                             bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  610.                         }else{
  611.                             bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  612.                         }
  613.                     }
  614.                 }

  615.                 /**
  616.                  * OLD ALIAS
  617.             if(aliasOrderByDistinct.size()>0){
  618.                 bf.append(SQLQueryObjectCore.ORDER_BY_SEPARATOR);
  619.                 Iterator<String> it = aliasOrderByDistinct.iterator();
  620.                 boolean first = true;
  621.                 while(it.hasNext()){
  622.                     if(!first)
  623.                         bf.append(",");
  624.                     else
  625.                         first = false;
  626.                     bf.append(it.next());
  627.                 }
  628.                 if(this.sortTypeAsc){
  629.                     bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  630.                 }else{
  631.                     bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  632.                 }
  633.             }
  634.                  */
  635.                
  636.             }else{

  637.                 // Offset non presente

  638.                 // Table dove effettuare la ricerca 'FromTable'
  639.                 if(this.tables.isEmpty()){
  640.                     throw new SQLQueryObjectException(SQLQueryObjectCore.TABELLA_RICERCA_FROM_NON_DEFINITA);
  641.                 }else{

  642.                     if(delete && this.tables.size()>2)
  643.                         throw new SQLQueryObjectException("Non e' possibile effettuare una delete con piu' di una tabella alla volta");

  644.                     Iterator<String> it = this.tables.iterator();
  645.                     boolean first = true;
  646.                     while(it.hasNext()){
  647.                         if(!first)
  648.                             bf.append(",");
  649.                         else
  650.                             first = false;
  651.                         bf.append(it.next());
  652.                     }
  653.                 }

  654.                 // Condizioni di Where
  655.                 if(!this.conditions.isEmpty()){
  656.                     bf.append(SQLQueryObjectCore.WHERE_SEPARATOR);

  657.                     if(this.notBeforeConditions){
  658.                         bf.append("NOT (");
  659.                     }

  660.                     for(int i=0; i<this.conditions.size(); i++){
  661.                         if(i>0){
  662.                             if(this.andLogicOperator){
  663.                                 bf.append(SQLQueryObjectCore.AND_SEPARATOR);
  664.                             }else{
  665.                                 bf.append(SQLQueryObjectCore.OR_SEPARATOR);
  666.                             }
  667.                         }
  668.                         bf.append(this.conditions.get(i));
  669.                     }

  670.                     if(this.notBeforeConditions){
  671.                         bf.append(")");
  672.                     }

  673.                 }

  674.                 // Condizione GroupBy
  675.                 if((!this.getGroupByConditions().isEmpty()) && (!delete)){
  676.                     bf.append(SQLQueryObjectCore.GROUP_BY_SEPARATOR);
  677.                     Iterator<String> it = this.getGroupByConditions().iterator();
  678.                     boolean first = true;
  679.                     while(it.hasNext()){
  680.                         if(!first)
  681.                             bf.append(",");
  682.                         else
  683.                             first = false;
  684.                         bf.append(it.next());
  685.                     }
  686.                 }

  687.                 // Condizione OrderBy
  688.                 if(!union &&
  689.                     ((!this.orderBy.isEmpty()) && (!delete))
  690.                     ){
  691.                     bf.append(SQLQueryObjectCore.ORDER_BY_SEPARATOR);
  692.                     Iterator<String> it = this.orderBy.iterator();
  693.                     boolean first = true;
  694.                     while(it.hasNext()){
  695.                         String column = it.next();
  696.                         if(!first)
  697.                             bf.append(",");
  698.                         else
  699.                             first = false;
  700.                         bf.append(column);
  701.                         boolean sortTypeAsc = this.sortTypeAsc;
  702.                         if(this.orderBySortType.containsKey(column)){
  703.                             sortTypeAsc = this.orderBySortType.get(column);
  704.                         }
  705.                         if(sortTypeAsc){
  706.                             bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  707.                         }else{
  708.                             bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  709.                         }
  710.                     }
  711.                 }
  712.                
  713.                 // ForUpdate
  714.                 if(this.selectForUpdate){
  715.                     bf.append(" FOR UPDATE ");
  716.                 }
  717.             }
  718.         }else{

  719.             // UPDATE, conditions

  720.             // Condizioni di Where
  721.             if(!this.conditions.isEmpty()){

  722.                 if(!conditions)
  723.                     bf.append(SQLQueryObjectCore.WHERE_SEPARATOR);

  724.                 if(this.notBeforeConditions){
  725.                     bf.append("NOT (");
  726.                 }

  727.                 for(int i=0; i<this.conditions.size(); i++){
  728.                     if(i>0){
  729.                         if(this.andLogicOperator){
  730.                             bf.append(SQLQueryObjectCore.AND_SEPARATOR);
  731.                         }else{
  732.                             bf.append(SQLQueryObjectCore.OR_SEPARATOR);
  733.                         }
  734.                     }
  735.                     bf.append(this.conditions.get(i));
  736.                 }

  737.                 if(this.notBeforeConditions){
  738.                     bf.append(")");
  739.                 }

  740.             }
  741.            
  742.             // Non genero per le condizioni, per update viene sollevata eccezione prima
  743.             // ForUpdate
  744. /**         if(this.selectForUpdate){
  745. //              bf.append(" FOR UPDATE ");
  746. //          }*/
  747.         }

  748.         return bf.toString();
  749.     }
  750.    
  751.    
  752.     @Override
  753.     public String createSQLUnion(boolean unionAll,
  754.             ISQLQueryObject... sqlQueryObject) throws SQLQueryObjectException {

  755.         // Controllo parametro su cui effettuare la UNION
  756.         this.checkUnionField(false,sqlQueryObject);

  757.         if(this.selectForUpdate){
  758.             this.checkSelectForUpdate(false, false, true);
  759.         }
  760.        
  761.         StringBuilder bf = new StringBuilder();

  762.         // Non ha senso, la union fa gia la distinct, a meno di usare la unionAll ma in quel caso non si vuole la distinct
  763.         /** if(this.isSelectDistinct())
  764.         //  bf.append(" DISTINCT ");*/

  765.         // Se e' presente Offset o Limit
  766.         // Rilascio vincolo di order by in caso di limit impostato.
  767.         // Il vincolo rimane per l'offset, per gestire le select annidate di qualche implementazioni come Oracle,SQLServer ...
  768.         /**if( (this.offset>=0 || this.limit>=0) ){*/
  769.         if( this.offset>=0 ){

  770.             bf.append("SELECT * from ");

  771.             bf.append(SQLQueryObjectCore.SELECT_SEPARATOR_CON_INIZIO_APERTURA);

  772.             if(this.fields.isEmpty()){
  773.                 Iterator<String> it = this.tableNames.iterator();
  774.                 boolean first = true;
  775.                 while(it.hasNext()){
  776.                     if(!first)
  777.                         bf.append(",");
  778.                     else
  779.                         first = false;
  780.                     String t = it.next();
  781.                     bf.append(t+".*");
  782.                 }
  783.             }else{
  784.                 Iterator<String> it = this.fields.iterator();
  785.                 boolean first = true;
  786.                 while(it.hasNext()){
  787.                     if(!first)
  788.                         bf.append(",");
  789.                     else
  790.                         first = false;
  791.                     String f = it.next();
  792.                     bf.append(f);
  793.                 }
  794.             }

  795.             bf.append(" , ROW_NUMBER() OVER ( ORDER BY ");

  796.             // Condizione OrderBy
  797.             if(this.orderBy.isEmpty()){
  798.                 throw new SQLQueryObjectException(SQLQueryObjectCore.CONDIZIONI_ORDER_BY_RICHESTE);
  799.             }
  800.             if(!this.orderBy.isEmpty()){
  801.                 Iterator<String> it = this.orderBy.iterator();
  802.                 boolean first = true;
  803.                 while(it.hasNext()){
  804.                     if(!first)
  805.                         bf.append(",");
  806.                     else
  807.                         first = false;
  808.                     String condizione = it.next();
  809.                     if(this.alias.containsKey(condizione)){
  810.                         bf.append(this.alias.get(condizione));
  811.                     }else{
  812.                         bf.append(condizione);
  813.                     }
  814.                     boolean sortTypeAsc = this.sortTypeAsc;
  815.                     if(this.orderBySortType.containsKey(condizione)){
  816.                         sortTypeAsc = this.orderBySortType.get(condizione);
  817.                     }
  818.                     if(sortTypeAsc){
  819.                         bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  820.                     }else{
  821.                         bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  822.                     }
  823.                 }
  824.             }

  825.             bf.append(" ) AS rowNumber ");

  826.             // Table dove effettuare la ricerca 'FromTable'
  827.             bf.append(SQLQueryObjectCore.FROM_SEPARATOR_APERTURA);

  828.             for(int i=0; i<sqlQueryObject.length; i++){

  829.                 if(((DB2QueryObject)sqlQueryObject[i]).selectForUpdate){
  830.                     try{
  831.                         ((DB2QueryObject)sqlQueryObject[i]).checkSelectForUpdate(false, false, true);
  832.                     }catch(Exception e){
  833.                         throw new SQLQueryObjectException("Parametro SqlQueryObject["+i+"] non valido: "+e.getMessage());
  834.                     }
  835.                 }
  836.                
  837.                 if(i>0){
  838.                     bf.append(" UNION ");
  839.                     if(unionAll){
  840.                         bf.append(" ALL ");
  841.                     }
  842.                 }

  843.                 bf.append("( ");

  844.                 bf.append(((DB2QueryObject)sqlQueryObject[i]).createSQLQuery(true));

  845.                 bf.append(") ");
  846.             }

  847.             bf.append(SQLQueryObjectCore.AS_SUBQUERY_SUFFIX+getSerial()+" ");

  848.             // Condizioni di Where
  849.             if(!this.conditions.isEmpty()){

  850.                 bf.append(SQLQueryObjectCore.WHERE_SEPARATOR);

  851.                 if(this.notBeforeConditions){
  852.                     bf.append(SQLQueryObjectCore.NOT_SEPARATOR_APERTURA);
  853.                 }

  854.                 for(int i=0; i<this.conditions.size(); i++){

  855.                     if(i>0){
  856.                         if(this.andLogicOperator){
  857.                             bf.append(SQLQueryObjectCore.AND_SEPARATOR);
  858.                         }else{
  859.                             bf.append(SQLQueryObjectCore.OR_SEPARATOR);
  860.                         }
  861.                     }
  862.                     String cond = this.conditions.get(i);
  863.                     bf.append(cond);
  864.                 }

  865.                 if(this.notBeforeConditions){
  866.                     bf.append(" )");
  867.                 }
  868.             }

  869.             // Condizione GroupBy
  870.             if((!this.getGroupByConditions().isEmpty())){
  871.                 bf.append(SQLQueryObjectCore.GROUP_BY_SEPARATOR);
  872.                 Iterator<String> it = this.getGroupByConditions().iterator();
  873.                 boolean first = true;
  874.                 while(it.hasNext()){
  875.                     if(!first)
  876.                         bf.append(",");
  877.                     else
  878.                         first = false;
  879.                     bf.append(it.next());
  880.                 }
  881.             }

  882.             bf.append(SQLQueryObjectCore.AS_SUBQUERY_SUFFIX+getSerial()+" ");

  883.             bf.append(" WHERE ( ");
  884.             if(this.offset>=0){
  885.                 bf.append(" rowNumber > ");
  886.                 bf.append(this.offset);
  887.             }
  888.             if(this.limit>=0){
  889.                 if(this.offset>=0)
  890.                     bf.append(" AND");
  891.                 bf.append(" rowNumber <=  ");
  892.                 if(this.offset>=0)
  893.                     bf.append(this.offset+this.limit);
  894.                 else
  895.                     bf.append(this.limit);
  896.             }
  897.             bf.append(" )");


  898.         }else{

  899.             // no offset

  900.             bf.append("SELECT ");


  901.             Iterator<String> itForceIndex = this.forceIndexTableNames.iterator();
  902.             while(itForceIndex.hasNext()){
  903.                 bf.append(" "+itForceIndex.next()+" ");
  904.             }

  905.             if(this.fields.isEmpty()){
  906.                 bf.append("*");
  907.             }else{
  908.                 Iterator<String> it = this.fields.iterator();
  909.                 boolean first = true;
  910.                 while(it.hasNext()){
  911.                     if(!first)
  912.                         bf.append(",");
  913.                     else
  914.                         first = false;
  915.                     String f = it.next();
  916.                     bf.append(f);
  917.                 }
  918.             }

  919.             bf.append(SQLQueryObjectCore.FROM_SEPARATOR_APERTURA);

  920.             for(int i=0; i<sqlQueryObject.length; i++){

  921.                 if(((DB2QueryObject)sqlQueryObject[i]).selectForUpdate){
  922.                     try{
  923.                         ((DB2QueryObject)sqlQueryObject[i]).checkSelectForUpdate(false, false, true);
  924.                     }catch(Exception e){
  925.                         throw new SQLQueryObjectException("Parametro SqlQueryObject["+i+"] non valido: "+e.getMessage());
  926.                     }
  927.                 }
  928.                
  929.                 if(i>0){
  930.                     bf.append(" UNION ");
  931.                     if(unionAll){
  932.                         bf.append(" ALL ");
  933.                     }
  934.                 }

  935.                 bf.append("( ");

  936.                 bf.append(((DB2QueryObject)sqlQueryObject[i]).createSQLQuery(true));

  937.                 bf.append(") ");
  938.             }

  939.             bf.append(SQLQueryObjectCore.AS_SUBQUERY_SUFFIX+getSerial()+" ");


  940.             // Condizione GroupBy
  941.             if((!this.getGroupByConditions().isEmpty())){
  942.                 bf.append(SQLQueryObjectCore.GROUP_BY_SEPARATOR);
  943.                 Iterator<String> it = this.getGroupByConditions().iterator();
  944.                 boolean first = true;
  945.                 while(it.hasNext()){
  946.                     if(!first)
  947.                         bf.append(",");
  948.                     else
  949.                         first = false;
  950.                     bf.append(it.next());
  951.                 }
  952.             }

  953.             // Condizione OrderBy
  954.             if(!this.orderBy.isEmpty()){
  955.                 bf.append(SQLQueryObjectCore.ORDER_BY_SEPARATOR);
  956.                 Iterator<String> it = this.orderBy.iterator();
  957.                 boolean first = true;
  958.                 while(it.hasNext()){
  959.                     String column = it.next();
  960.                     if(!first)
  961.                         bf.append(",");
  962.                     else
  963.                         first = false;
  964.                     bf.append(column);
  965.                     boolean sortTypeAsc = this.sortTypeAsc;
  966.                     if(this.orderBySortType.containsKey(column)){
  967.                         sortTypeAsc = this.orderBySortType.get(column);
  968.                     }
  969.                     if(sortTypeAsc){
  970.                         bf.append(SQLQueryObjectCore.ASC_SEPARATOR);
  971.                     }else{
  972.                         bf.append(SQLQueryObjectCore.DESC_SEPARATOR);
  973.                     }
  974.                 }
  975.             }

  976.             // Limit (senza offset)
  977.             if(this.offset<0 && this.limit>0){
  978.                 bf.append(" FETCH FIRST ");
  979.                 bf.append(this.limit);
  980.                 bf.append(" ROWS ONLY ");
  981.             }
  982.         }

  983.         return bf.toString();
  984.     }

  985.     @Override
  986.     public String createSQLUnionCount(boolean unionAll, String aliasCount,
  987.             ISQLQueryObject... sqlQueryObject) throws SQLQueryObjectException {

  988.         // Controllo parametro su cui effettuare la UNION
  989.         this.checkUnionField(true,sqlQueryObject);

  990.         if(aliasCount==null){
  991.             throw new SQLQueryObjectException("Alias per il count non definito");
  992.         }

  993.         StringBuilder bf = new StringBuilder();

  994.         bf.append("SELECT count(*) "+this.getDefaultAliasFieldKeyword()+" ");
  995.         bf.append(aliasCount);
  996.         bf.append(SQLQueryObjectCore.FROM_SEPARATOR_APERTURA);

  997.         bf.append( this.createSQLUnion(unionAll, sqlQueryObject) );

  998.         bf.append(SQLQueryObjectCore.AS_SUBQUERY_SUFFIX+getSerial()+" ");

  999.         return bf.toString();
  1000.     }

  1001.     @Override
  1002.     public String createSQLUpdateEngine() throws SQLQueryObjectException {
  1003.        
  1004.         StringBuilder bf = new StringBuilder();
  1005.         bf.append("UPDATE ");
  1006.         bf.append(this.updateTable);
  1007.         bf.append(" SET ");
  1008.         for(int i=0; i<this.updateFieldsName.size(); i++){
  1009.             if(i>0)
  1010.                 bf.append(" , ");
  1011.             bf.append(this.updateFieldsName.get(i));
  1012.             bf.append(" = ");
  1013.             bf.append(this.updateFieldsValue.get(i));
  1014.         }
  1015.         bf.append(getSQL(false,true,false,false));
  1016.         return bf.toString();
  1017.     }








  1018.     /* ---------------- WHERE CONDITIONS ------------------ */

  1019.     @Override
  1020.     public String createSQLConditionsEngine() throws SQLQueryObjectException {
  1021.        
  1022.         StringBuilder bf = new StringBuilder();
  1023.         bf.append(getSQL(false,false,true,false));
  1024.         return bf.toString();
  1025.     }



  1026. }