Class SqlGenerationVisitor

  • All Implemented Interfaces:
    SqlGenerator, com.exasol.adapter.sql.SqlNodeVisitor<String>

    public class SqlGenerationVisitor
    extends Object
    implements com.exasol.adapter.sql.SqlNodeVisitor<String>, SqlGenerator
    This class has the logic to generate SQL queries based on a graph of SqlNode elements. It uses the visitor pattern. This class interacts with the dialects in some situations, e.g. to find out how to handle quoting, case-sensitivity.

    If this class is not sufficiently customizable for your use case, you can extend this class and override the required methods. You also have to return your custom visitor class then in the method SqlDialect.getSqlGenerator(SqlGenerationContext).

    Note on operator associativity and parenthesis generation: Currently we almost always use parenthesis. Without parenthesis, two SqlNode graphs with different semantic lead to select 1 = 1 - 1 + 1. Also SELECT NOT NOT TRUE needs to be written as SELECT NOT (NOT TRUE) to work at all, whereas SELECT NOT TRUE works fine without parentheses. Currently we make inflationary use of parenthesis to enforce the right semantic, but hopefully there is a better way.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      protected void checkDialectAliases()
      Check if dialect provided invalid aliases, which would never be applied.
      protected String createExplicitColumnsSelectList​(com.exasol.adapter.sql.SqlSelectList selectList)
      Create a list of explicitly specified columns (where columns can also be expressions) for a SELECT list.
      String generateSqlFor​(com.exasol.adapter.sql.SqlNode sqlNode)
      Generate a SQL representation of the pass SqlNode.
      protected SqlDialect getDialect()
      Get the SQL dialect.
      protected String getTypeNameFromColumn​(com.exasol.adapter.sql.SqlColumn column)
      Get the type name for a column
      protected boolean isDirectlyInSelectList​(com.exasol.adapter.sql.SqlColumn column)
      Check if a column is directly in the select list.
      protected String representAnyColumnInSelectList()
      Represent "any column" in the SELECT list.
      String visit​(com.exasol.adapter.sql.SqlColumn column)  
      String visit​(com.exasol.adapter.sql.SqlFunctionAggregate function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionAggregateGroupConcat function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionAggregateListagg sqlFunctionAggregateListagg)  
      String visit​(com.exasol.adapter.sql.SqlFunctionScalar function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionScalarCase function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionScalarCast function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionScalarExtract function)  
      String visit​(com.exasol.adapter.sql.SqlFunctionScalarJsonValue function)  
      String visit​(com.exasol.adapter.sql.SqlGroupBy groupBy)  
      String visit​(com.exasol.adapter.sql.SqlJoin join)  
      String visit​(com.exasol.adapter.sql.SqlLimit limit)  
      String visit​(com.exasol.adapter.sql.SqlLiteralBool literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralDate literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralDouble literal)
      Get a value of the double converted to an E-notation format.
      String visit​(com.exasol.adapter.sql.SqlLiteralExactnumeric literal)
      Formats a value of the exactnumeric as a plain string without E notation.
      String visit​(com.exasol.adapter.sql.SqlLiteralInterval literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralNull literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralString literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralTimestamp literal)  
      String visit​(com.exasol.adapter.sql.SqlLiteralTimestampUtc literal)  
      String visit​(com.exasol.adapter.sql.SqlOrderBy orderBy)  
      String visit​(com.exasol.adapter.sql.SqlPredicateAnd predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateBetween predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateEqual predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateInConstList predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateIsJson function)  
      String visit​(com.exasol.adapter.sql.SqlPredicateIsNotJson function)  
      String visit​(com.exasol.adapter.sql.SqlPredicateIsNotNull predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateIsNull predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateLess predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateLessEqual predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateLike predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateLikeRegexp predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateNot predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateNotEqual predicate)  
      String visit​(com.exasol.adapter.sql.SqlPredicateOr predicate)  
      String visit​(com.exasol.adapter.sql.SqlSelectList selectList)  
      String visit​(com.exasol.adapter.sql.SqlStatementSelect select)  
      String visit​(com.exasol.adapter.sql.SqlTable table)  
    • Method Detail

      • generateSqlFor

        public String generateSqlFor​(com.exasol.adapter.sql.SqlNode sqlNode)
                              throws com.exasol.adapter.AdapterException
        Description copied from interface: SqlGenerator
        Generate a SQL representation of the pass SqlNode.
        Specified by:
        generateSqlFor in interface SqlGenerator
        Parameters:
        sqlNode - sqlNode
        Returns:
        SQL representation
        Throws:
        com.exasol.adapter.AdapterException - if an error occurs while generating the SQL representation.
      • getDialect

        protected SqlDialect getDialect()
        Get the SQL dialect.
        Returns:
        SQL dialect.
      • checkDialectAliases

        protected void checkDialectAliases()
        Check if dialect provided invalid aliases, which would never be applied.
      • isDirectlyInSelectList

        protected boolean isDirectlyInSelectList​(com.exasol.adapter.sql.SqlColumn column)
        Check if a column is directly in the select list.
        Parameters:
        column - column name
        Returns:
        true if the column is directly in the select list of a query
      • visit

        public String visit​(com.exasol.adapter.sql.SqlStatementSelect select)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlSelectList selectList)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • representAnyColumnInSelectList

        protected String representAnyColumnInSelectList()
        Represent "any column" in the SELECT list.

        A typical example are queries where the only thing that matters if what you searched for exists or not. Different databases have different preferred ways of expressing this kind of result.

        Returns:
        always "true"
      • createExplicitColumnsSelectList

        protected String createExplicitColumnsSelectList​(com.exasol.adapter.sql.SqlSelectList selectList)
                                                  throws com.exasol.adapter.AdapterException
        Create a list of explicitly specified columns (where columns can also be expressions) for a SELECT list.
        Parameters:
        selectList - list of columns (or expressions) in the SELECT part
        Returns:
        string representing the SELECT list
        Throws:
        com.exasol.adapter.AdapterException - in case the expressions in the list cannot be rendered to SQL
      • visit

        public String visit​(com.exasol.adapter.sql.SqlColumn column)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlTable table)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlJoin join)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionAggregateListagg sqlFunctionAggregateListagg)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlGroupBy groupBy)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionAggregate function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionAggregateGroupConcat function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionScalar function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionScalarCase function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionScalarCast function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionScalarExtract function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlFunctionScalarJsonValue function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLimit limit)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralBool literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralDate literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralDouble literal)
        Get a value of the double converted to an E-notation format.

        For example: 1.234 becomes 1.234E0

        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralExactnumeric literal)
        Formats a value of the exactnumeric as a plain string without E notation.

        For example: 1E-35 becomes 0.00000000000000000000000000000000001

        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralNull literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralString literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralTimestamp literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralTimestampUtc literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlLiteralInterval literal)
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
      • visit

        public String visit​(com.exasol.adapter.sql.SqlOrderBy orderBy)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateAnd predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateBetween predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateEqual predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateInConstList predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateIsJson function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateIsNotJson function)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateLess predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateLessEqual predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateLike predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateLikeRegexp predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateNot predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateNotEqual predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateOr predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateIsNull predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • visit

        public String visit​(com.exasol.adapter.sql.SqlPredicateIsNotNull predicate)
                     throws com.exasol.adapter.AdapterException
        Specified by:
        visit in interface com.exasol.adapter.sql.SqlNodeVisitor<String>
        Throws:
        com.exasol.adapter.AdapterException
      • getTypeNameFromColumn

        protected String getTypeNameFromColumn​(com.exasol.adapter.sql.SqlColumn column)
                                        throws com.exasol.adapter.AdapterException
        Get the type name for a column
        Parameters:
        column - column
        Returns:
        type name
        Throws:
        com.exasol.adapter.AdapterException - if something goes wrong