polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [03/19] polygene-java git commit: Bring in Stanislav's sql-generator from GutHub, after his consent in https://lists.apache.org/thread.html/797352ce2ad7aa7b755720a98f545a176e6050e35f56db113ba115fb@%3Cdev.polygene.apache.org%3E
Date Sat, 15 Apr 2017 08:25:54 GMT
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java
new file mode 100644
index 0000000..835ada1
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ModificationProcessing.java
@@ -0,0 +1,291 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.Iterator;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByQuery;
+import org.apache.polygene.library.sql.generator.grammar.modification.ColumnSourceByValues;
+import org.apache.polygene.library.sql.generator.grammar.modification.DeleteBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.DynamicColumnSource;
+import org.apache.polygene.library.sql.generator.grammar.modification.InsertStatement;
+import org.apache.polygene.library.sql.generator.grammar.modification.SetClause;
+import org.apache.polygene.library.sql.generator.grammar.modification.TargetTable;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateBySearch;
+import org.apache.polygene.library.sql.generator.grammar.modification.UpdateSourceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ModificationProcessing
+{
+
+    public static abstract class DynamicColumnSourceProcessor<SourceType extends DynamicColumnSource>
+        extends
+        AbstractProcessor<SourceType>
+    {
+        public DynamicColumnSourceProcessor( Class<? extends SourceType> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SourceType object,
+                                  StringBuilder builder )
+        {
+            if( object.getColumnNames() != null )
+            {
+                processor.process( object.getColumnNames(), builder );
+            }
+            this.doProcessColumnSource( processor, object, builder );
+        }
+
+        protected abstract void doProcessColumnSource( SQLProcessorAggregator processor,
+                                                       SourceType object,
+                                                       StringBuilder builder );
+    }
+
+    public static class ColumnSourceByQueryProcessor extends
+                                                     DynamicColumnSourceProcessor<ColumnSourceByQuery>
+    {
+
+        public ColumnSourceByQueryProcessor()
+        {
+            this( ColumnSourceByQuery.class );
+        }
+
+        protected ColumnSourceByQueryProcessor( Class<? extends ColumnSourceByQuery> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessColumnSource( SQLProcessorAggregator processor,
+                                              ColumnSourceByQuery object,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.NEWLINE );
+            processor.process( object.getQuery(), builder );
+        }
+    }
+
+    public static class ColumnSourceByValuesProcessor extends
+                                                      DynamicColumnSourceProcessor<ColumnSourceByValues>
+    {
+
+        public ColumnSourceByValuesProcessor()
+        {
+            this( ColumnSourceByValues.class );
+        }
+
+        public ColumnSourceByValuesProcessor( Class<? extends ColumnSourceByValues> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessColumnSource( SQLProcessorAggregator processor,
+                                              ColumnSourceByValues object,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.NEWLINE ).append( "VALUES" )
+                   .append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<ValueExpression> iter = object.getValues().iterator();
+            while( iter.hasNext() )
+            {
+                ValueExpression next = iter.next();
+                boolean needParenthesis = next instanceof QueryExpression;
+                if( needParenthesis )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS );
+                }
+                processor.process( next, builder );
+                if( needParenthesis )
+                {
+                    builder.append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class DeleteBySearchProcessor extends AbstractProcessor<DeleteBySearch>
+    {
+        public DeleteBySearchProcessor()
+        {
+            this( DeleteBySearch.class );
+        }
+
+        public DeleteBySearchProcessor( Class<? extends DeleteBySearch> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, DeleteBySearch object,
+                                  StringBuilder builder )
+        {
+            builder.append( "DELETE FROM" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTargetTable(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              object.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+        }
+    }
+
+    public static class InsertStatementProcessor extends AbstractProcessor<InsertStatement>
+    {
+        public InsertStatementProcessor()
+        {
+            this( InsertStatement.class );
+        }
+
+        public InsertStatementProcessor( Class<? extends InsertStatement> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, InsertStatement object,
+                                  StringBuilder builder )
+        {
+            builder.append( "INSERT INTO" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTableName(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getColumnSource(), builder );
+        }
+    }
+
+    public static class SetClauseProcessor extends AbstractProcessor<SetClause>
+    {
+        public SetClauseProcessor()
+        {
+            this( SetClause.class );
+        }
+
+        public SetClauseProcessor( Class<? extends SetClause> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SetClause object,
+                                  StringBuilder builder )
+        {
+            builder.append( object.getUpdateTarget() ).append( SQLConstants.TOKEN_SEPARATOR )
+                   .append( "=" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getUpdateSource(), builder );
+        }
+    }
+
+    public static class TargetTableProcessor extends AbstractProcessor<TargetTable>
+    {
+        public TargetTableProcessor()
+        {
+            this( TargetTable.class );
+        }
+
+        protected TargetTableProcessor( Class<? extends TargetTable> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TargetTable object,
+                                  StringBuilder builder )
+        {
+            Boolean isOnly = object.isOnly();
+            if( isOnly )
+            {
+                builder.append( "ONLY" ).append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            processor.process( object.getTableName(), builder );
+            if( isOnly )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+    }
+
+    public static class UpdateBySearchProcessor extends AbstractProcessor<UpdateBySearch>
+    {
+        public UpdateBySearchProcessor()
+        {
+            this( UpdateBySearch.class );
+        }
+
+        protected UpdateBySearchProcessor( Class<? extends UpdateBySearch> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, UpdateBySearch object,
+                                  StringBuilder builder )
+        {
+            builder.append( "UPDATE" ).append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( object.getTargetTable(), builder );
+            builder.append( SQLConstants.NEWLINE ).append( "SET" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            Iterator<SetClause> iter = object.getSetClauses().iterator();
+            while( iter.hasNext() )
+            {
+                processor.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              object.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+        }
+    }
+
+    public static class UpdateSourceByExpressionProcessor extends
+                                                          AbstractProcessor<UpdateSourceByExpression>
+    {
+        public UpdateSourceByExpressionProcessor()
+        {
+            this( UpdateSourceByExpression.class );
+        }
+
+        public UpdateSourceByExpressionProcessor( Class<? extends UpdateSourceByExpression> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor,
+                                  UpdateSourceByExpression object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getValueExpression(), builder );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java
new file mode 100644
index 0000000..e6bc330
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/NoOpProcessor.java
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+public class NoOpProcessor
+    implements SQLProcessor
+{
+
+    public void process( SQLProcessorAggregator processor, Typeable<?> object, StringBuilder builder )
+    {
+        // No-op
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java
new file mode 100644
index 0000000..15bb6b3
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/ProcessorUtils.java
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.SetQuantifier;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropBehaviour;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class ProcessorUtils
+{
+    public static Boolean notNullAndNotEmpty( String str )
+    {
+        return str != null && str.trim().length() > 0;
+    }
+
+    public static void processSetQuantifier( SetQuantifier quantifier, StringBuilder builder )
+    {
+        if( quantifier == SetQuantifier.ALL )
+        {
+            builder.append( "ALL" );
+        }
+        else
+        {
+            builder.append( "DISTINCT" );
+        }
+    }
+
+    public static void processDropBehaviour( DropBehaviour behaviour, StringBuilder builder )
+    {
+        builder.append( SQLConstants.TOKEN_SEPARATOR );
+        if( behaviour == DropBehaviour.CASCADE )
+        {
+            builder.append( "CASCADE" );
+        }
+        else
+        {
+            builder.append( "RESTRICT" );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java
new file mode 100644
index 0000000..e49bf15
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/QueryProcessing.java
@@ -0,0 +1,615 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.booleans.BooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.NonBooleanExpression;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.ValueExpression;
+import org.apache.polygene.library.sql.generator.grammar.literals.LiteralExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences;
+import org.apache.polygene.library.sql.generator.grammar.query.ColumnReferences.ColumnReferenceInfo;
+import org.apache.polygene.library.sql.generator.grammar.query.CorrespondingSpec;
+import org.apache.polygene.library.sql.generator.grammar.query.FromClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.GroupingElement;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OrderByClause;
+import org.apache.polygene.library.sql.generator.grammar.query.Ordering;
+import org.apache.polygene.library.sql.generator.grammar.query.OrdinaryGroupingSet;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBody;
+import org.apache.polygene.library.sql.generator.grammar.query.QueryExpressionBodyBinary;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.RowDefinition;
+import org.apache.polygene.library.sql.generator.grammar.query.RowSubQuery;
+import org.apache.polygene.library.sql.generator.grammar.query.RowValueConstructor;
+import org.apache.polygene.library.sql.generator.grammar.query.SelectColumnClause;
+import org.apache.polygene.library.sql.generator.grammar.query.SetOperation;
+import org.apache.polygene.library.sql.generator.grammar.query.SortSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReference;
+import org.apache.polygene.library.sql.generator.grammar.query.TableValueConstructor;
+import org.apache.polygene.library.sql.generator.implementation.grammar.booleans.BooleanUtils;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class QueryProcessing
+{
+
+    public static void processOptionalBooleanExpression( SQLProcessorAggregator processor,
+                                                         StringBuilder builder,
+                                                         BooleanExpression expression, String prefix, String name )
+    {
+        if( expression != null && !BooleanUtils.isEmpty( expression ) )
+        {
+            processOptional( processor, builder, expression, prefix, name );
+        }
+    }
+
+    public static void processOptional( SQLProcessorAggregator processor, StringBuilder builder,
+                                        Typeable<?> element,
+                                        String prefix, String name )
+    {
+        if( element != null )
+        {
+            builder.append( prefix );
+            if( name != null )
+            {
+                builder.append( name ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+            processor.process( element, builder );
+        }
+    }
+
+    public static class QueryExpressionBinaryProcessor extends
+                                                       AbstractProcessor<QueryExpressionBodyBinary>
+    {
+        private static final Map<SetOperation, String> _defaultSetOperations;
+
+        static
+        {
+            Map<SetOperation, String> operations = new HashMap<SetOperation, String>();
+            operations.put( SetOperation.EXCEPT, "EXCEPT" );
+            operations.put( SetOperation.INTERSECT, "INTERSECT" );
+            operations.put( SetOperation.UNION, "UNION" );
+            _defaultSetOperations = operations;
+        }
+
+        private final Map<SetOperation, String> _setOperations;
+
+        public QueryExpressionBinaryProcessor()
+        {
+            this( _defaultSetOperations );
+        }
+
+        public QueryExpressionBinaryProcessor( Map<SetOperation, String> setOperations )
+        {
+            super( QueryExpressionBodyBinary.class );
+            Objects.requireNonNull( setOperations, "set operations" );
+            this._setOperations = setOperations;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QueryExpressionBodyBinary body,
+                                  StringBuilder builder )
+        {
+            Boolean leftIsNotEmpty =
+                body.getLeft() != QueryExpressionBody.EmptyQueryExpressionBody.INSTANCE;
+            if( leftIsNotEmpty )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS );
+                processor.process( body.getLeft(), builder );
+                builder.append( SQLConstants.CLOSE_PARENTHESIS ).append( SQLConstants.NEWLINE );
+                this.processSetOperation( body.getSetOperation(), builder );
+
+                builder.append( SQLConstants.TOKEN_SEPARATOR );
+                ProcessorUtils.processSetQuantifier( body.getSetQuantifier(), builder );
+
+                CorrespondingSpec correspondingCols = body.getCorrespondingColumns();
+                if( correspondingCols != null )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR );
+                    processor.process( correspondingCols, builder );
+                }
+
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.OPEN_PARENTHESIS );
+            }
+            processor.process( body.getRight(), builder );
+            if( leftIsNotEmpty )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+        }
+
+        protected void processSetOperation( SetOperation operation, StringBuilder builder )
+        {
+            builder.append( this._setOperations.get( operation ) );
+        }
+    }
+
+    public static class QuerySpecificationProcessor extends AbstractProcessor<QuerySpecification>
+    {
+
+        public QuerySpecificationProcessor()
+        {
+            this( QuerySpecification.class );
+        }
+
+        public QuerySpecificationProcessor( Class<? extends QuerySpecification> queryClass )
+        {
+            super( queryClass );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QuerySpecification query,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.SELECT ).append( SQLConstants.TOKEN_SEPARATOR );
+            ProcessorUtils.processSetQuantifier( query.getColumns().getSetQuantifier(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+
+            processor.process( query.getColumns(), builder );
+            processor.process( query.getFrom(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder, query.getWhere(),
+                                                              SQLConstants.NEWLINE, SQLConstants.WHERE );
+            processor.process( query.getGroupBy(), builder );
+            QueryProcessing.processOptionalBooleanExpression( processor, builder,
+                                                              query.getHaving(),
+                                                              SQLConstants.NEWLINE, SQLConstants.HAVING );
+            processor.process( query.getOrderBy(), builder );
+            Typeable<?> first = null;
+            Typeable<?> second = null;
+            if( this.isOffsetBeforeLimit( processor ) )
+            {
+                first = query.getOffsetSpecification();
+                second = query.getLimitSpecification();
+            }
+            else
+            {
+                first = query.getLimitSpecification();
+                second = query.getOffsetSpecification();
+            }
+
+            if( first != null || second != null )
+            {
+                this.processLimitAndOffset( processor, builder, first, second );
+            }
+
+            if( query.getOrderBy() == null
+                && ( query.getOffsetSpecification() != null || query.getLimitSpecification() != null ) )
+            {
+                LoggerFactory.getLogger( this.getClass().getName() ).warn(
+                    "Spotted query with " + SQLConstants.OFFSET_PREFIX + " and/or "
+                    + SQLConstants.LIMIT_PREFIX
+                    + " clause, but without ORDER BY. The result will be unpredictable!"
+                    + "\n" + "Query: "
+                    + builder.toString() );
+            }
+        }
+
+        protected boolean isOffsetBeforeLimit( SQLProcessorAggregator processor )
+        {
+            return true;
+        }
+
+        protected void processLimitAndOffset( SQLProcessorAggregator processor,
+                                              StringBuilder builder,
+                                              Typeable<?> first, Typeable<?> second )
+        {
+            QueryProcessing.processOptional( processor, builder, first, SQLConstants.NEWLINE, null );
+            QueryProcessing
+                .processOptional( processor, builder, second, SQLConstants.NEWLINE, null );
+        }
+    }
+
+    public static class SelectColumnsProcessor extends AbstractProcessor<SelectColumnClause>
+    {
+        public SelectColumnsProcessor()
+        {
+            super( SelectColumnClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SelectColumnClause select,
+                                  StringBuilder builder )
+        {
+            if( select instanceof ColumnReferences )
+            {
+                Iterator<ColumnReferenceInfo> iter =
+                    ( (ColumnReferences) select ).getColumns().iterator();
+                while( iter.hasNext() )
+                {
+                    ColumnReferenceInfo info = iter.next();
+                    aggregator.process( info.getReference(), builder );
+                    String alias = info.getAlias();
+                    if( ProcessorUtils.notNullAndNotEmpty( alias ) )
+                    {
+                        builder.append( SQLConstants.TOKEN_SEPARATOR )
+                               .append( SQLConstants.ALIAS_DEFINER )
+                               .append( SQLConstants.TOKEN_SEPARATOR ).append( alias );
+                    }
+
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+            else
+            {
+                builder.append( SQLConstants.ASTERISK );
+            }
+        }
+    }
+
+    public static class FromProcessor extends AbstractProcessor<FromClause>
+    {
+        public FromProcessor()
+        {
+            super( FromClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, FromClause from,
+                                  StringBuilder builder )
+        {
+            if( !from.getTableReferences().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.FROM )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<TableReference> iter = from.getTableReferences().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next().asTypeable(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class QueryExpressionProcessor extends AbstractProcessor<QueryExpression>
+    {
+        public QueryExpressionProcessor()
+        {
+            super( QueryExpression.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, QueryExpression object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getQueryExpressionBody(), builder );
+        }
+    }
+
+    public static class CorrespondingSpecProcessor extends AbstractProcessor<CorrespondingSpec>
+    {
+        public CorrespondingSpecProcessor()
+        {
+            super( CorrespondingSpec.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, CorrespondingSpec object,
+                                  StringBuilder builder )
+        {
+            builder.append( "CORRESPONDING" );
+            if( object.getColumnList() != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "BY" )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                processor.process( object.getColumnList(), builder );
+            }
+        }
+    }
+
+    public static class SortSpecificationProcessor extends AbstractProcessor<SortSpecification>
+    {
+        private static final Map<Ordering, String> _defaultOrderingStrings;
+
+        static
+        {
+            Map<Ordering, String> map = new HashMap<Ordering, String>();
+            map.put( Ordering.ASCENDING, "ASC" );
+            map.put( Ordering.DESCENDING, "DESC" );
+            _defaultOrderingStrings = map;
+        }
+
+        private final Map<Ordering, String> _orderingStrings;
+
+        public SortSpecificationProcessor()
+        {
+            this( _defaultOrderingStrings );
+        }
+
+        public SortSpecificationProcessor( Map<Ordering, String> orderingStrings )
+        {
+            super( SortSpecification.class );
+            Objects.requireNonNull( orderingStrings, "ordering strings" );
+            this._orderingStrings = orderingStrings;
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, SortSpecification object,
+                                  StringBuilder builder )
+        {
+            processor.process( object.getValueExpression(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append(
+                this._orderingStrings.get( object.getOrderingSpecification() ) );
+        }
+    }
+
+    public static class OrdinaryGroupingSetProcessor extends AbstractProcessor<OrdinaryGroupingSet>
+    {
+        public OrdinaryGroupingSetProcessor()
+        {
+            super( OrdinaryGroupingSet.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, OrdinaryGroupingSet object,
+                                  StringBuilder builder )
+        {
+            Iterator<NonBooleanExpression> iter = object.getColumns().iterator();
+            while( iter.hasNext() )
+            {
+                processor.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+        }
+    }
+
+    public static class GroupByProcessor extends AbstractProcessor<GroupByClause>
+    {
+        public GroupByProcessor()
+        {
+            super( GroupByClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, GroupByClause groupBy,
+                                  StringBuilder builder )
+        {
+            if( !groupBy.getGroupingElements().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.GROUP_BY )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<GroupingElement> iter = groupBy.getGroupingElements().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class OrderByProcessor extends AbstractProcessor<OrderByClause>
+    {
+        public OrderByProcessor()
+        {
+            super( OrderByClause.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, OrderByClause orderBy,
+                                  StringBuilder builder )
+        {
+            if( !orderBy.getOrderingColumns().isEmpty() )
+            {
+                builder.append( SQLConstants.NEWLINE ).append( SQLConstants.ORDER_BY )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                Iterator<SortSpecification> iter = orderBy.getOrderingColumns().iterator();
+                while( iter.hasNext() )
+                {
+                    aggregator.process( iter.next(), builder );
+                    if( iter.hasNext() )
+                    {
+                        builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                    }
+                }
+            }
+        }
+    }
+
+    public static class TableValueConstructorProcessor extends
+                                                       AbstractProcessor<TableValueConstructor>
+    {
+        public TableValueConstructorProcessor()
+        {
+            super( TableValueConstructor.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, TableValueConstructor object,
+                                  StringBuilder builder )
+        {
+            builder.append( "VALUES" ).append( SQLConstants.TOKEN_SEPARATOR );
+            Iterator<RowValueConstructor> iter = object.getRows().iterator();
+            while( iter.hasNext() )
+            {
+                aggregator.process( iter.next(), builder );
+                if( iter.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+        }
+    }
+
+    public static class RowSubQueryProcessor extends AbstractProcessor<RowSubQuery>
+    {
+        public RowSubQueryProcessor()
+        {
+            super( RowSubQuery.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, RowSubQuery object,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            aggregator.process( object.getQueryExpression(), builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class RowDefinitionProcessor extends AbstractProcessor<RowDefinition>
+    {
+        public RowDefinitionProcessor()
+        {
+            super( RowDefinition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, RowDefinition object,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            Iterator<ValueExpression> vals = object.getRowElements().iterator();
+            while( vals.hasNext() )
+            {
+                aggregator.process( vals.next(), builder );
+                if( vals.hasNext() )
+                {
+                    builder.append( SQLConstants.COMMA ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+            }
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static class OffsetSpecificationProcessor extends AbstractProcessor<OffsetSpecification>
+    {
+
+        public OffsetSpecificationProcessor()
+        {
+            super( OffsetSpecification.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, OffsetSpecification object,
+                                  StringBuilder builder )
+        {
+            String prefix = this.getPrefix( aggregator );
+            if( prefix != null )
+            {
+                builder.append( prefix ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+            NonBooleanExpression skip = object.getSkip();
+            boolean isComplex = !( skip instanceof LiteralExpression );
+            if( isComplex )
+            {
+                builder.append( SQLConstants.OPEN_PARENTHESIS ).append( SQLConstants.NEWLINE );
+            }
+            aggregator.process( skip, builder );
+            if( isComplex )
+            {
+                builder.append( SQLConstants.CLOSE_PARENTHESIS );
+            }
+            String postfix = this.getPostfix( aggregator );
+            if( postfix != null )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( postfix );
+            }
+        }
+
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.OFFSET_PREFIX;
+        }
+
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.OFFSET_POSTFIX;
+        }
+    }
+
+    public static class LimitSpecificationProcessor extends AbstractProcessor<LimitSpecification>
+    {
+        public LimitSpecificationProcessor()
+        {
+            super( LimitSpecification.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, LimitSpecification object,
+                                  StringBuilder builder )
+        {
+            NonBooleanExpression count = this.getRealCount( object.getCount() );
+            if( count != null )
+            {
+                String prefix = this.getPrefix( aggregator );
+                if( prefix != null )
+                {
+                    builder.append( prefix ).append( SQLConstants.TOKEN_SEPARATOR );
+                }
+                boolean isComplex = !( count instanceof LiteralExpression );
+                if( isComplex )
+                {
+                    builder.append( SQLConstants.OPEN_PARENTHESIS ).append( SQLConstants.NEWLINE );
+                }
+                aggregator.process( count, builder );
+                if( isComplex )
+                {
+                    builder.append( SQLConstants.CLOSE_PARENTHESIS );
+                }
+                String postfix = this.getPostfix( aggregator );
+                if( postfix != null )
+                {
+                    builder.append( SQLConstants.TOKEN_SEPARATOR ).append( postfix );
+                }
+            }
+        }
+
+        protected NonBooleanExpression getRealCount( NonBooleanExpression limitCount )
+        {
+            return limitCount;
+        }
+
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.LIMIT_PREFIX;
+        }
+
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return SQLConstants.LIMIT_POSTFIX;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java
new file mode 100644
index 0000000..151b4f7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/TableReferenceProcessing.java
@@ -0,0 +1,354 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
+
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.common.TableName;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.query.TableAlias;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByExpression;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferenceByName;
+import org.apache.polygene.library.sql.generator.grammar.query.TableReferencePrimary;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.CrossJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinCondition;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinType;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.JoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NamedColumnsJoin;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.NaturalJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.QualifiedJoinedTable;
+import org.apache.polygene.library.sql.generator.grammar.query.joins.UnionJoinedTable;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableReferenceProcessing
+{
+
+    public static abstract class AbstractTableNameProcessor<TableNameType extends TableName>
+        extends
+        AbstractProcessor<TableNameType>
+    {
+
+        protected AbstractTableNameProcessor( Class<? extends TableNameType> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameType object,
+                                  StringBuilder builder )
+        {
+            String schemaName = object.getSchemaName();
+            if( ProcessorUtils.notNullAndNotEmpty( schemaName ) )
+            {
+                builder.append( schemaName ).append( SQLConstants.SCHEMA_TABLE_SEPARATOR );
+            }
+            this.doProcessTableName( processor, object, builder );
+        }
+
+        protected abstract void doProcessTableName( SQLProcessorAggregator processor,
+                                                    TableNameType object,
+                                                    StringBuilder builder );
+    }
+
+    public static class TableNameFunctionProcessor extends
+                                                   AbstractTableNameProcessor<TableNameFunction>
+    {
+
+        public TableNameFunctionProcessor()
+        {
+            this( TableNameFunction.class );
+        }
+
+        protected TableNameFunctionProcessor( Class<? extends TableNameFunction> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessTableName( SQLProcessorAggregator processor,
+                                           TableNameFunction object,
+                                           StringBuilder builder )
+        {
+            processor.process( object.getFunction(), builder );
+        }
+    }
+
+    public static class TableNameDirectProcessor extends
+                                                 AbstractTableNameProcessor<TableNameDirect>
+    {
+
+        public TableNameDirectProcessor()
+        {
+            this( TableNameDirect.class );
+        }
+
+        protected TableNameDirectProcessor( Class<? extends TableNameDirect> realType )
+        {
+            super( realType );
+        }
+
+        @Override
+        protected void doProcessTableName( SQLProcessorAggregator processor,
+                                           TableNameDirect object,
+                                           StringBuilder builder )
+        {
+            builder.append( object.getTableName() );
+        }
+    }
+
+    public static abstract class TableReferencePrimaryProcessor<TableReferenceType extends TableReferencePrimary>
+        extends AbstractProcessor<TableReferenceType>
+    {
+        public TableReferencePrimaryProcessor( Class<TableReferenceType> realType )
+        {
+            super( realType );
+        }
+
+        protected void doProcess( SQLProcessorAggregator processor, TableReferenceType object,
+                                  StringBuilder builder )
+        {
+            this.doProcessTablePrimary( processor, object, builder );
+            if( object.getTableAlias() != null )
+            {
+                this.processTableAlias( processor, object.getTableAlias(), builder );
+            }
+        }
+
+        protected abstract void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                                       TableReferenceType object,
+                                                       StringBuilder builder );
+
+        protected void processTableAlias( SQLProcessorAggregator processor, TableAlias tableAlias,
+                                          StringBuilder builder )
+        {
+            String alias = tableAlias.getTableAlias();
+            if( ProcessorUtils.notNullAndNotEmpty( alias ) )
+            {
+                builder.append( SQLConstants.TOKEN_SEPARATOR ).append( SQLConstants.ALIAS_DEFINER )
+                       .append( SQLConstants.TOKEN_SEPARATOR ).append( alias );
+
+                if( tableAlias.getColumnAliases() != null )
+                {
+                    processor.process( tableAlias.getColumnAliases(), builder );
+                }
+            }
+        }
+    }
+
+    public static class TableReferenceByNameProcessor extends
+                                                      TableReferencePrimaryProcessor<TableReferenceByName>
+    {
+        public TableReferenceByNameProcessor()
+        {
+            super( TableReferenceByName.class );
+        }
+
+        @Override
+        protected void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                              TableReferenceByName object,
+                                              StringBuilder builder )
+        {
+            processor.process( object.getTableName(), builder );
+        }
+    }
+
+    public static class TableReferenceByExpressionProcessor extends
+                                                            TableReferencePrimaryProcessor<TableReferenceByExpression>
+    {
+        public TableReferenceByExpressionProcessor()
+        {
+            super( TableReferenceByExpression.class );
+        }
+
+        @Override
+        protected void doProcessTablePrimary( SQLProcessorAggregator processor,
+                                              TableReferenceByExpression tableRef,
+                                              StringBuilder builder )
+        {
+            builder.append( SQLConstants.OPEN_PARENTHESIS );
+            processor.process( tableRef.getQuery(), builder );
+            builder.append( SQLConstants.CLOSE_PARENTHESIS );
+        }
+    }
+
+    public static abstract class JoinedTableProcessor<JoinedTableType extends JoinedTable> extends
+                                                                                           AbstractProcessor<JoinedTableType>
+    {
+
+        public JoinedTableProcessor( Class<JoinedTableType> realType )
+        {
+            super( realType );
+        }
+
+        protected void doProcess( SQLProcessorAggregator processor, JoinedTableType table,
+                                  StringBuilder builder )
+        {
+            processor.process( table.getLeft().asTypeable(), builder );
+            builder.append( SQLConstants.NEWLINE );
+            this.doProcessJoinedTable( processor, table, builder );
+        }
+
+        protected abstract void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                                      JoinedTableType table,
+                                                      StringBuilder builder );
+
+        protected void processJoinType( JoinType joinType, StringBuilder builder )
+        {
+            if( joinType != null )
+            {
+                if( joinType == JoinType.INNER )
+                {
+                    builder.append( "INNER " );
+                }
+                else
+                {
+                    if( joinType == JoinType.FULL_OUTER )
+                    {
+                        builder.append( "FULL " );
+                    }
+                    else if( joinType == JoinType.LEFT_OUTER )
+                    {
+                        builder.append( "LEFT " );
+                    }
+                    else
+                    // if (joinType == JoinType.RIGHT_OUTER)
+                    {
+                        builder.append( "RIGHT " );
+                    }
+                }
+                builder.append( "JOIN" ).append( SQLConstants.TOKEN_SEPARATOR );
+            }
+        }
+    }
+
+    public static class CrossJoinedTableProcessor extends JoinedTableProcessor<CrossJoinedTable>
+    {
+        public CrossJoinedTableProcessor()
+        {
+            super( CrossJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             CrossJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "CROSS JOIN" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class NaturalJoinedTableProcessor extends
+                                                    JoinedTableProcessor<NaturalJoinedTable>
+    {
+        public NaturalJoinedTableProcessor()
+        {
+            super( NaturalJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             NaturalJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "NATURAL" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            this.processJoinType( table.getJoinType(), builder );
+            builder.append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class QualifiedJoinedTableProcessor extends
+                                                      JoinedTableProcessor<QualifiedJoinedTable>
+    {
+        public QualifiedJoinedTableProcessor()
+        {
+            super( QualifiedJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             QualifiedJoinedTable table,
+                                             StringBuilder builder )
+        {
+            this.processJoinType( table.getJoinType(), builder );
+            processor.process( table.getRight().asTypeable(), builder );
+            processor.process( table.getJoinSpecification(), builder );
+        }
+    }
+
+    public static class UnionJoinedTableProcessor extends JoinedTableProcessor<UnionJoinedTable>
+    {
+        public UnionJoinedTableProcessor()
+        {
+            super( UnionJoinedTable.class );
+        }
+
+        @Override
+        protected void doProcessJoinedTable( SQLProcessorAggregator processor,
+                                             UnionJoinedTable table,
+                                             StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "UNION JOIN" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( table.getRight().asTypeable(), builder );
+        }
+    }
+
+    public static class JoinConditionProcessor extends AbstractProcessor<JoinCondition>
+    {
+        public JoinConditionProcessor()
+        {
+            super( JoinCondition.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, JoinCondition condition,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "ON" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+            processor.process( condition.getSearchConidition(), builder );
+        }
+    }
+
+    public static class NamedColumnsJoinProcessor extends AbstractProcessor<NamedColumnsJoin>
+    {
+        public NamedColumnsJoinProcessor()
+        {
+            super( NamedColumnsJoin.class );
+        }
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, NamedColumnsJoin join,
+                                  StringBuilder builder )
+        {
+            builder.append( SQLConstants.TOKEN_SEPARATOR ).append( "USING" )
+                   .append( SQLConstants.TOKEN_SEPARATOR );
+
+            processor.process( join.getColumnNames(), builder );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java
new file mode 100644
index 0000000..afc7d35
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/derby/DerbyProcessor.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.derby;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class DerbyProcessor extends DefaultSQLProcessor
+{
+
+    public DerbyProcessor( SQLVendor vendor )
+    {
+        super( vendor, DefaultSQLProcessor.getDefaultProcessors() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java
new file mode 100644
index 0000000..8176980
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/h2/H2Processor.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.h2;
+
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+public class H2Processor
+    extends DefaultSQLProcessor
+{
+
+    public H2Processor( SQLVendor vendor )
+    {
+        super( vendor, DefaultSQLProcessor.getDefaultProcessors() );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java
new file mode 100644
index 0000000..3ccc96f
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/DefinitionProcessing.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.SchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefinitionProcessing
+{
+
+    public static class MySQLSchemaDefinitionProcessor extends SchemaDefinitionProcessor
+    {
+
+        @Override
+        protected void doProcess( SQLProcessorAggregator aggregator, SchemaDefinition object, StringBuilder builder )
+        {
+            // Just process schema elements
+            this.processSchemaElements( aggregator, object, builder );
+        }
+    }
+
+    public static class MySQLColumnDefinitionProcessor extends ColumnDefinitionProcessor
+    {
+        @Override
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            // MySQL combines both ALWAYS and BY DEFAULT policies.
+            builder.append( " AUTO_INCREMENT" );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java
new file mode 100644
index 0000000..dc036f6
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/MySQLProcessor.java
@@ -0,0 +1,81 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.grammar.definition.schema.SchemaDefinition;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.grammar.manipulation.DropSchemaStatement;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.QuerySpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefaultSQLProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.NoOpProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.DefinitionProcessing.MySQLColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.DefinitionProcessing.MySQLSchemaDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLLimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLOffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.QueryProcessing.MySQLQuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.TableProcessing.MySQLTableNameDirectProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.mysql.TableProcessing.MySQLTableNameFunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessor;
+import org.apache.polygene.library.sql.generator.vendor.SQLVendor;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class MySQLProcessor extends DefaultSQLProcessor
+{
+
+    private static final Map<Class<? extends Typeable<?>>, SQLProcessor> _defaultProcessors;
+
+    static
+    {
+        Map<Class<? extends Typeable<?>>, SQLProcessor> processors = new HashMap<Class<? extends Typeable<?>>, SQLProcessor>(
+            DefaultSQLProcessor.getDefaultProcessors() );
+
+        // MySQL does not understand schema-qualified table names (or anything related to schemas)
+        processors.put( TableNameDirect.class, new MySQLTableNameDirectProcessor() );
+        processors.put( TableNameFunction.class, new MySQLTableNameFunctionProcessor() );
+
+        // Only process schema elements from schema definition, and ignore drop schema statements
+        processors.put( SchemaDefinition.class, new MySQLSchemaDefinitionProcessor() );
+        processors.put( DropSchemaStatement.class, new NoOpProcessor() );
+
+        // Override default column definition support
+        processors.put( ColumnDefinition.class, new MySQLColumnDefinitionProcessor() );
+
+        // Different syntax for OFFSET/FETCH
+        processors.put( QuerySpecification.class, new MySQLQuerySpecificationProcessor() );
+        processors.put( OffsetSpecification.class, new MySQLOffsetSpecificationProcessor() );
+        processors.put( LimitSpecification.class, new MySQLLimitSpecificationProcessor() );
+
+        _defaultProcessors = processors;
+    }
+
+    public MySQLProcessor( SQLVendor vendor )
+    {
+        super( vendor, _defaultProcessors );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java
new file mode 100644
index 0000000..7324418
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/QueryProcessing.java
@@ -0,0 +1,114 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.Typeable;
+import org.apache.polygene.library.sql.generator.grammar.common.SQLConstants;
+import org.apache.polygene.library.sql.generator.grammar.query.LimitSpecification;
+import org.apache.polygene.library.sql.generator.grammar.query.OffsetSpecification;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.LimitSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.OffsetSpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.QueryProcessing.QuerySpecificationProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+import org.apache.polygene.library.sql.generator.vendor.MySQLVendor;
+
+/**
+ * @author 2011 Stanislav Muhametsin
+ */
+public class QueryProcessing
+{
+    private static final String MYSQL_LIMIT_PREFIX = "LIMIT";
+    private static final String MYSQL_LIMIT_POSTFIX = null;
+    private static final String MYSQL_OFFSET_PREFIX = "OFFSET";
+    private static final String MYSQL_OFFSET_POSTFIX = null;
+
+    public static class MySQLQuerySpecificationProcessor extends QuerySpecificationProcessor
+    {
+        @Override
+        protected boolean isOffsetBeforeLimit( SQLProcessorAggregator processor )
+        {
+            return false;
+        }
+
+        @Override
+        protected void processLimitAndOffset( SQLProcessorAggregator processor, StringBuilder builder,
+                                              Typeable<?> first, Typeable<?> second )
+        {
+            MySQLVendor vendor = (MySQLVendor) processor.getVendor();
+            if( vendor.legacyLimit() )
+            {
+                // Just do the processing right away, because of the difference of syntax
+                builder.append( SQLConstants.NEWLINE ).append( MYSQL_LIMIT_PREFIX )
+                       .append( SQLConstants.TOKEN_SEPARATOR );
+                if( second != null )
+                {
+                    processor.process( ( (OffsetSpecification) second ).getSkip(), builder );
+                    builder.append( SQLConstants.COMMA );
+                }
+                if( first != null && ( (LimitSpecification) first ).getCount() != null )
+                {
+                    processor.process( ( (LimitSpecification) first ).getCount(), builder );
+                }
+                else if( second != null )
+                {
+                    builder.append( Long.MAX_VALUE );
+                }
+            }
+            else
+            {
+                if( first == null && second != null )
+                {
+                    first = vendor.getQueryFactory().limit( vendor.getLiteralFactory().n( Long.MAX_VALUE ) );
+                }
+                super.processLimitAndOffset( processor, builder, first, second );
+            }
+        }
+    }
+
+    public static class MySQLOffsetSpecificationProcessor extends OffsetSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_OFFSET_PREFIX;
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_OFFSET_POSTFIX;
+        }
+    }
+
+    public static class MySQLLimitSpecificationProcessor extends LimitSpecificationProcessor
+    {
+        @Override
+        protected String getPrefix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_LIMIT_PREFIX;
+        }
+
+        @Override
+        protected String getPostfix( SQLProcessorAggregator processor )
+        {
+            return MYSQL_LIMIT_POSTFIX;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java
new file mode 100644
index 0000000..e209b07
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/mysql/TableProcessing.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.mysql;
+
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameDirect;
+import org.apache.polygene.library.sql.generator.grammar.common.TableNameFunction;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameDirectProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.TableReferenceProcessing.TableNameFunctionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class TableProcessing
+{
+    public static class MySQLTableNameDirectProcessor extends TableNameDirectProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameDirect object, StringBuilder builder )
+        {
+            // MySQL does not understand schema-qualified table names
+            builder.append( object.getTableName() );
+        }
+    }
+
+    public static class MySQLTableNameFunctionProcessor extends TableNameFunctionProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TableNameFunction object, StringBuilder builder )
+        {
+            // MySQL does not understand schema-qualified table names
+            processor.process( object.getFunction(), builder );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java
new file mode 100644
index 0000000..1560a29
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+/**
+ * This package contains the default processors for syntax elements defined in API. The vendor uses these processors (or custom processors) to create textual SQL statement out of API syntax elements.
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java
new file mode 100644
index 0000000..2eb78fa
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/DefinitionProcessing.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import java.util.Map;
+import java.util.Objects;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.AutoGenerationPolicy;
+import org.apache.polygene.library.sql.generator.grammar.definition.table.ColumnDefinition;
+import org.apache.polygene.library.sql.generator.implementation.transformation.DefinitionProcessing.ColumnDefinitionProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class DefinitionProcessing
+{
+    public static class PGColumnDefinitionProcessor extends ColumnDefinitionProcessor
+    {
+        private final Map<Class<?>, String> _dataTypeSerialNames;
+
+        public PGColumnDefinitionProcessor( Map<Class<?>, String> dataTypeSerialNames )
+        {
+            Objects.requireNonNull( dataTypeSerialNames, "Data type serial names" );
+            this._dataTypeSerialNames = dataTypeSerialNames;
+        }
+
+        @Override
+        protected void processDataType( SQLProcessorAggregator aggregator, ColumnDefinition object,
+                                        StringBuilder builder )
+        {
+            AutoGenerationPolicy autoGenPolicy = object.getAutoGenerationPolicy();
+            if( autoGenPolicy == null )
+            {
+                super.processDataType( aggregator, object, builder );
+            }
+            else
+            {
+                // PostgreSQL can't handle the ALWAYS strategy
+                if( AutoGenerationPolicy.BY_DEFAULT.equals( autoGenPolicy ) )
+                {
+                    // Don't produce default data type if auto generated
+                    Class<?> dtClass = object.getDataType().getClass();
+                    Boolean success = false;
+                    for( Map.Entry<Class<?>, String> entry : this._dataTypeSerialNames.entrySet() )
+                    {
+                        success = entry.getKey().isAssignableFrom( dtClass );
+                        if( success )
+                        {
+                            builder.append( entry.getValue() );
+                            break;
+                        }
+                    }
+                    if( !success )
+                    {
+                        throw new UnsupportedOperationException( "Unsupported column data type " + object.getDataType()
+                                                                 + " for auto-generated column." );
+                    }
+                }
+                else
+                {
+                    throw new UnsupportedOperationException( "Unsupported auto generation policy: " + autoGenPolicy
+                                                             + "." );
+                }
+            }
+        }
+
+        @Override
+        protected void processAutoGenerationPolicy( ColumnDefinition object, StringBuilder builder )
+        {
+            // Nothing to do - auto generation policy handled in data type orc
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/a36086b6/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java
----------------------------------------------------------------------
diff --git a/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java
new file mode 100644
index 0000000..de1dae7
--- /dev/null
+++ b/libraries/sql-generator/src/main/java/org/apache/polygene/library/sql/generator/implementation/transformation/pgsql/LiteralExpressionProcessing.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.library.sql.generator.implementation.transformation.pgsql;
+
+import org.apache.polygene.library.sql.generator.grammar.literals.TimestampTimeLiteral;
+import org.apache.polygene.library.sql.generator.implementation.transformation.LiteralExpressionProcessing.DateTimeLiteralProcessor;
+import org.apache.polygene.library.sql.generator.implementation.transformation.spi.SQLProcessorAggregator;
+
+/**
+ * @author Stanislav Muhametsin
+ */
+public class LiteralExpressionProcessing
+{
+    public static class PGDateTimeLiteralProcessor extends DateTimeLiteralProcessor
+    {
+        @Override
+        protected void doProcess( SQLProcessorAggregator processor, TimestampTimeLiteral object, StringBuilder builder )
+        {
+            builder.append( "timestamp " );
+            super.doProcess( processor, object, builder );
+        }
+    }
+}


Mime
View raw message