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 ); + } + } +}
