package it.unibz.inf.ontop.generation.serializer.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import it.unibz.inf.ontop.dbschema.*;
import it.unibz.inf.ontop.generation.algebra.SQLRelationVisitor;
import it.unibz.inf.ontop.generation.algebra.SQLValuesExpression;
import it.unibz.inf.ontop.generation.algebra.SelectFromWhereWithModifiers;
import it.unibz.inf.ontop.generation.serializer.SelectFromWhereSerializer;
import it.unibz.inf.ontop.model.term.TermFactory;
import it.unibz.inf.ontop.model.term.Variable;
import it.unibz.inf.ontop.utils.ImmutableCollectors;

import java.util.AbstractMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Singleton
public class H2SelectFromWhereSerializer extends DefaultSelectFromWhereSerializer implements SelectFromWhereSerializer {

    @Inject
    private H2SelectFromWhereSerializer(TermFactory termFactory) {
        super(new DefaultSQLTermSerializer(termFactory));
    }

    @Override
    public SelectFromWhereSerializer.QuerySerialization serialize(SelectFromWhereWithModifiers selectFromWhere, DBParameters dbParameters) {
        return selectFromWhere.acceptVisitor(
                new DefaultRelationVisitingSerializer(dbParameters.getQuotedIDFactory()) {
                    /**
                     * Number of rows in output can be limited either with standard OFFSET / FETCH,
                     * with non-standard LIMIT / OFFSET, or with non-standard TOP clauses.
                     * Different clauses cannot be used together. OFFSET specifies how many rows to skip.
                     * Please note that queries with high offset values can be slow.
                     * FETCH FIRST/NEXT, LIMIT or TOP limits the number of rows returned by the query
                     * (no limit if null or smaller than zero). If PERCENT is specified number of rows
                     * is specified as a percent of the total number of rows and should be an integer
                     * value between 0 and 100 inclusive. WITH TIES can be used only together with
                     * ORDER BY and means that all additional rows that have the same sorting position
                     * as the last row will be also returned.
                     *
                     * LIMIT expression [OFFSET expression]
                     * OFFSET expression ROW|ROWS FETCH FIRST|(NEXT expression) [PERCENT]
                     */

                    // serializeLimit is standard

                    @Override
                    protected String serializeLimitOffset(long limit, long offset, boolean noSortCondition) {
                        return String.format("OFFSET %d ROWS\nFETCH NEXT %d ROWS ONLY", offset, limit);
                    }

                    @Override
                    protected String serializeOffset(long offset, boolean noSortCondition) {
                        return String.format("OFFSET %d ROWS", offset);
                    }

                });
    }

    protected class DefaultRelationVisitingSerializer extends DefaultSelectFromWhereSerializer.DefaultRelationVisitingSerializer
            implements SQLRelationVisitor<QuerySerialization> {

        protected DefaultRelationVisitingSerializer(QuotedIDFactory idFactory) {
            super(idFactory);
        }

        @Override
        public QuerySerialization visit(SQLValuesExpression sqlValuesExpression) {

            // Leaf node
            ImmutableMap<Variable, QualifiedAttributeID> childColumnIDs = ImmutableMap.of();

            String tuplesSerialized = sqlValuesExpression.getValues().stream()
                    .map(tuple -> tuple.stream()
                            .map(constant -> sqlTermSerializer.serialize(constant, childColumnIDs))
                            .collect(Collectors.joining(",", " (", ")")))
                    .collect(Collectors.joining(","));

            RelationID alias = generateFreshViewAlias();

            String sql = "(VALUES " + tuplesSerialized + " AS " + alias + " )";

            ImmutableList<Variable> orderedVariables = sqlValuesExpression.getOrderedVariables();

            // Map the column names generated by VALUES in h2 to projected variables
            ImmutableMap<Variable, QualifiedAttributeID> columnIDs = orderedVariables.stream()
                    .collect(ImmutableCollectors.toMap(
                            variable -> variable,
                            variable -> new QualifiedAttributeID(null, idFactory.createAttributeID(
                                    alias + ".C" + (orderedVariables.indexOf(variable) + 1)))));

            return new QuerySerializationImpl(sql, columnIDs);
        }
    }
}

@@ -148,55 +148,8 @@
 ap;%0A
-import com.google.common.collect.ImmutableSet;%0A
 impo
@@ -255,73 +255,8 @@
 .*;%0A
-import it.unibz.inf.ontop.generation.algebra.SQLRelationVisitor;%0A
 impo
@@ -622,38 +622,8 @@
 s;%0A%0A
-import java.util.AbstractMap;%0A
 impo
@@ -657,43 +657,8 @@
 ors;
-%0Aimport java.util.stream.IntStream;
 %0A%0A@S
@@ -2955,323 +2955,278 @@
     
-%7D);%0A    %7D%0A%0A    protected class DefaultRelationVisitingSerializer extends DefaultSelectFromWhereSerializer.DefaultRel
+    @Override%0A                    public QuerySerializ
 ation
-V
+ v
 isit
-ingSerializer%0A            implements SQLRelationVisitor%3CQuerySerialization%3E %7B%0A%0A        protected DefaultRelationVisitingSerializer(QuotedIDFactory idFactory) %7B%0A            super(idFactory);
+(SQLValuesExpression sqlValuesExpression) %7B%0A%0A                        // H2 version 2+ and above aligned with other SQL dialects%0A                        // H2 version 1 requires special aliasing conventions
 %0A   
@@ -3230,27 +3230,24 @@
         
-%7D%0A%0A
         
 @Overrid
@@ -3242,102 +3242,77 @@
     
-@Override%0A        public QuerySerialization visit(SQLValuesExpression sqlValuesExpression) %7B%0A%0A
+        if (dbParameters.getDbmsVersion().startsWith(%221%22)) %7B%0A        
     
@@ -3319,16 +3319,24 @@
         
+        
 // Leaf 
@@ -3340,16 +3340,32 @@
 af node%0A
+                
         
@@ -3458,24 +3458,40 @@
             
+         
+       
 String tuple
@@ -3561,24 +3561,40 @@
             
+                
 .map(tuple -
@@ -3634,24 +3634,40 @@
             
+     
+           
 .map(constan
@@ -3746,32 +3746,48 @@
                 
+                
 .collect(Collect
@@ -3828,32 +3828,48 @@
                 
+ 
+               
 .collect(Collect
@@ -3884,24 +3884,40 @@
 ing(%22,%22));%0A%0A
+                
             
@@ -3958,24 +3958,40 @@
 ewAlias();%0A%0A
+                
             
@@ -4063,32 +4063,48 @@
 %22;%0A%0A            
+         
+       
 ImmutableList%3CVa
@@ -4186,16 +4186,32 @@
         
+       
+         
 // Map t
@@ -4279,32 +4279,48 @@
 les%0A            
+     
+           
 ImmutableMap%3CVar
@@ -4398,32 +4398,48 @@
                 
+                
 .collect(Immutab
@@ -4478,32 +4478,48 @@
                 
+ 
+               
 variable -%3E vari
@@ -4544,32 +4544,48 @@
                 
+             
+   
 variable -%3E new 
@@ -4676,16 +4676,32 @@
         
+                
 alias + 
@@ -4762,24 +4762,40 @@
             
+         
+       
 return new Q
@@ -4841,17 +4841,178 @@
         
-%7D
+                %7D else %7B%0A                            return super.visit(sqlValuesExpression);%0A                        %7D%0A                    %7D%0A%0A                %7D);
 %0A    %7D%0A%7D

Make H2 serialization dependent on version