package com.facebook.presto.sql.parser;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.testng.annotations.Test;

import java.util.List;

import static com.facebook.presto.sql.parser.StatementSplitter.Statement;
import static com.facebook.presto.sql.parser.StatementSplitter.squeezeStatement;
import static com.google.common.base.Preconditions.checkArgument;
import static org.testng.Assert.assertEquals;

public class TestStatementSplitter
{
    @Test
    public void testSplitterIncomplete()
    {
        StatementSplitter splitter = new StatementSplitter(" select * FROM foo  ");
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), "select * FROM foo");
    }

    @Test
    public void testSplitterEmptyInput()
    {
        StatementSplitter splitter = new StatementSplitter("");
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), "");
    }

    @Test
    public void testSplitterEmptyStatements()
    {
        StatementSplitter splitter = new StatementSplitter(";;;");
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), "");
    }

    @Test
    public void testSplitterSingle()
    {
        StatementSplitter splitter = new StatementSplitter("select * from foo;");
        assertEquals(splitter.getCompleteStatements(), statements("select * from foo", ";"));
        assertEquals(splitter.getPartialStatement(), "");
    }

    @Test
    public void testSplitterMultiple()
    {
        StatementSplitter splitter = new StatementSplitter(" select * from  foo ; select * from t; select * from ");
        assertEquals(splitter.getCompleteStatements(), statements("select * from  foo", ";", "select * from t", ";"));
        assertEquals(splitter.getPartialStatement(), "select * from");
    }

    @Test
    public void testSplitterMultipleWithEmpty()
    {
        StatementSplitter splitter = new StatementSplitter("; select * from  foo ; select * from t;;;select * from ");
        assertEquals(splitter.getCompleteStatements(), statements("select * from  foo", ";", "select * from t", ";"));
        assertEquals(splitter.getPartialStatement(), "select * from");
    }

    @Test
    public void testSplitterCustomDelimiters()
    {
        String sql = "// select * from  foo // select * from t;//select * from ";
        StatementSplitter splitter = new StatementSplitter(sql, ImmutableSet.of(";", "//"));
        assertEquals(splitter.getCompleteStatements(), statements("select * from  foo", "//", "select * from t", ";"));
        assertEquals(splitter.getPartialStatement(), "select * from");
    }

    @Test
    public void testSplitterErrorBeforeComplete()
    {
        StatementSplitter splitter = new StatementSplitter(" select * from z# oops ; select ");
        assertEquals(splitter.getCompleteStatements(), statements("select * from z# oops", ";"));
        assertEquals(splitter.getPartialStatement(), "select");
    }

    @Test
    public void testSplitterErrorAfterComplete()
    {
        StatementSplitter splitter = new StatementSplitter("select * from foo; select z# oops ");
        assertEquals(splitter.getCompleteStatements(), statements("select * from foo", ";"));
        assertEquals(splitter.getPartialStatement(), "select z# oops");
    }

    @Test
    public void testSplitterWithQuotedString()
    {
        String sql = "select 'foo bar' x from dual";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), sql);
    }

    @Test
    public void testSplitterWithIncompleteQuotedString()
    {
        String sql = "select 'foo', 'bar";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), sql);
    }

    @Test
    public void testSplitterWithEscapedSingleQuote()
    {
        String sql = "select 'hello''world' from dual;";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of(sql));
        assertEquals(splitter.getPartialStatement(), "");
    }

    @Test
    public void testSplitterWithQuotedIdentifier()
    {
        String sql = "select \"0\"\"bar\" from dual;";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of(sql));
        assertEquals(splitter.getPartialStatement(), "");
    }

    @Test
    public void testSplitterWithBackquote()
    {
        String sql = "select  ` f``o o ` from dual";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), sql);
    }

    @Test
    public void testSplitterWithDigitIdentifier()
    {
        String sql = "select   1x  from dual";
        StatementSplitter splitter = new StatementSplitter(sql);
        assertEquals(splitter.getCompleteStatements(), ImmutableList.of());
        assertEquals(splitter.getPartialStatement(), sql);
    }

    @Test
    public void testSqueezeStatement()
    {
        String sql = "select   *  from\n foo\n  order by x ; ";
        assertEquals(squeezeStatement(sql), "select * from foo order by x ;");
    }

    @Test
    public void testSqueezeStatementWithIncompleteQuotedString()
    {
        String sql = "select   *  from\n foo\n  where x = 'oops";
        assertEquals(squeezeStatement(sql), "select * from foo where x = 'oops");
    }

    @Test
    public void testSqueezeStatementWithBackquote()
    {
        String sql = "select  `  f``o  o`` `   from dual";
        assertEquals(squeezeStatement(sql), "select `  f``o  o`` ` from dual");
    }

    @Test
    public void testSqueezeStatementAlternateDelimiter()
    {
        String sql = "select   *  from\n foo\n  order by x // ";
        assertEquals(squeezeStatement(sql), "select * from foo order by x //");
    }

    @Test
    public void testSqueezeStatementError()
    {
        String sql = "select   *  from z#oops";
        assertEquals(squeezeStatement(sql), "select * from z#oops");
    }

    private static List<Statement> statements(String... args)
    {
        checkArgument(args.length % 2 == 0, "arguments not paired");
        ImmutableList.Builder<Statement> list = ImmutableList.builder();
        for (int i = 0; i < args.length; i += 2) {
            list.add(new Statement(args[i], args[i] + 1));
        }
        return list.build();
    }
}

@@ -4232,33 +4232,32 @@
 world' from dual
-;
 %22;%0A        State
@@ -4297,32 +4297,38 @@
 mentSplitter(sql
+ + %22;%22
 );%0A        asser
@@ -4369,36 +4369,35 @@
 ents(), 
-ImmutableList.of(sql
+statements(sql, %22;%22
 ));%0A    
@@ -4575,17 +4575,16 @@
 rom dual
-;
 %22;%0A     
@@ -4632,32 +4632,38 @@
 mentSplitter(sql
+ + %22;%22
 );%0A        asser
@@ -4708,28 +4708,27 @@
 (), 
-ImmutableList.of(sql
+statements(sql, %22;%22
 ));%0A
@@ -6811,13 +6811,13 @@
 gs%5Bi
-%5D
  + 1
+%5D
 ));%0A

Fix tests