content: /*
   * 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.cassandra.cql3.selection;
  
  import java.math.BigDecimal;
  import java.util.*;
  
  import org.junit.Test;
  
  import org.apache.cassandra.cql3.*;
  import org.apache.cassandra.db.marshal.*;
  import org.apache.cassandra.transport.messages.ResultMessage;
  
  import static org.junit.Assert.assertEquals;
  
  public class TermSelectionTest extends CQLTester
  {
      // Helper method for testSelectLiteral()
      private void assertConstantResult(UntypedResultSet result, Object constant)
      {
          assertRows(result,
                     row(1, "one", constant),
                     row(2, "two", constant),
                     row(3, "three", constant));
      }
  
      @Test
      public void testSelectLiteral() throws Throwable
      {
          long timestampInMicros = System.currentTimeMillis() * 1000;
          createTable("CREATE TABLE %s (pk int, ck int, t text, PRIMARY KEY (pk, ck) )");
          execute("INSERT INTO %s (pk, ck, t) VALUES (?, ?, ?) USING TIMESTAMP ?", 1, 1, "one", timestampInMicros);
          execute("INSERT INTO %s (pk, ck, t) VALUES (?, ?, ?) USING TIMESTAMP ?", 1, 2, "two", timestampInMicros);
          execute("INSERT INTO %s (pk, ck, t) VALUES (?, ?, ?) USING TIMESTAMP ?", 1, 3, "three", timestampInMicros);
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, 'a const' FROM %s");
          assertConstantResult(execute("SELECT ck, t, (text)'a const' FROM %s"), "a const");
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, 42 FROM %s");
          assertConstantResult(execute("SELECT ck, t, (smallint)42 FROM %s"), (short) 42);
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, (1, 'foo') FROM %s");
          assertConstantResult(execute("SELECT ck, t, (tuple<int, text>)(1, 'foo') FROM %s"), tuple(1, "foo"));
  
          assertInvalidMessage("Cannot infer type for term ((1)) in selection clause", "SELECT ck, t, ((1)) FROM %s");
          // We cannot differentiate a tuple containing a tuple from a tuple between parentheses.
          assertInvalidMessage("Cannot infer type for term ((tuple<int>)(1))", "SELECT ck, t, ((tuple<int>)(1)) FROM %s");
          assertConstantResult(execute("SELECT ck, t, (tuple<tuple<int>>)((1)) FROM %s"), tuple(tuple(1)));
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, [1, 2, 3] FROM %s");
          assertConstantResult(execute("SELECT ck, t, (list<int>)[1, 2, 3] FROM %s"), list(1, 2, 3));
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, {1, 2, 3} FROM %s");
          assertConstantResult(execute("SELECT ck, t, (set<int>){1, 2, 3} FROM %s"), set(1, 2, 3));
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, {1: 'foo', 2: 'bar', 3: 'baz'} FROM %s");
          assertConstantResult(execute("SELECT ck, t, (map<int, text>){1: 'foo', 2: 'bar', 3: 'baz'} FROM %s"), map(1, "foo", 2, "bar", 3, "baz"));
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ck, t, {} FROM %s");
          assertConstantResult(execute("SELECT ck, t, (map<int, text>){} FROM %s"), map());
          assertConstantResult(execute("SELECT ck, t, (set<int>){} FROM %s"), set());
  
          assertColumnNames(execute("SELECT ck, t, (int)42, (int)43 FROM %s"), "ck", "t", "(int)42", "(int)43");
          assertRows(execute("SELECT ck, t, (int) 42, (int) 43 FROM %s"),
                     row(1, "one", 42, 43),
                     row(2, "two", 42, 43),
                     row(3, "three", 42, 43));
  
          assertRows(execute("SELECT min(ck), max(ck), [min(ck), max(ck)] FROM %s"), row(1, 3, list(1, 3)));
          assertRows(execute("SELECT [min(ck), max(ck)] FROM %s"), row(list(1, 3)));
          assertRows(execute("SELECT {min(ck), max(ck)} FROM %s"), row(set(1, 3)));
  
          // We need to use a cast to differentiate between a map and an UDT
          assertInvalidMessage("Cannot infer type for term {'min': system.min(ck), 'max': system.max(ck)}",
                               "SELECT {'min' : min(ck), 'max' : max(ck)} FROM %s");
          assertRows(execute("SELECT (map<text, int>){'min' : min(ck), 'max' : max(ck)} FROM %s"), row(map("min", 1, "max", 3)));
  
          assertRows(execute("SELECT [1, min(ck), max(ck)] FROM %s"), row(list(1, 1, 3)));
          assertRows(execute("SELECT {1, min(ck), max(ck)} FROM %s"), row(set(1, 1, 3)));
          assertRows(execute("SELECT (map<text, int>) {'litteral' : 1, 'min' : min(ck), 'max' : max(ck)} FROM %s"), row(map("litteral", 1, "min", 1, "max", 3)));
  
          // Test List nested within Lists
          assertRows(execute("SELECT [[], [min(ck), max(ck)]] FROM %s"),
                     row(list(list(), list(1, 3))));
          assertRows(execute("SELECT [[], [CAST(pk AS BIGINT), CAST(ck AS BIGINT), WRITETIME(t)]] FROM %s"),
                     row(list(list(), list(1L, 1L, timestampInMicros))),
                     row(list(list(), list(1L, 2L, timestampInMicros))),
                     row(list(list(), list(1L, 3L, timestampInMicros))));
          assertRows(execute("SELECT [[min(ck)], [max(ck)]] FROM %s"),
                     row(list(list(1), list(3))));
          assertRows(execute("SELECT [[min(ck)], ([max(ck)])] FROM %s"),
                     row(list(list(1), list(3))));
          assertRows(execute("SELECT [[pk], [ck]] FROM %s"),
                     row(list(list(1), list(1))),
                     row(list(list(1), list(2))),
                     row(list(list(1), list(3))));
          assertRows(execute("SELECT [[pk], [ck]] FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(list(list(1), list(3))),
                     row(list(list(1), list(2))),
                     row(list(list(1), list(1))));
  
          // Test Sets nested within Lists
          assertRows(execute("SELECT [{}, {min(ck), max(ck)}] FROM %s"),
                     row(list(set(), set(1, 3))));
          assertRows(execute("SELECT [{}, {CAST(pk AS BIGINT), CAST(ck AS BIGINT), WRITETIME(t)}] FROM %s"),
                     row(list(set(), set(1L, 1L, timestampInMicros))),
                     row(list(set(), set(1L, 2L, timestampInMicros))),
                     row(list(set(), set(1L, 3L, timestampInMicros))));
          assertRows(execute("SELECT [{min(ck)}, {max(ck)}] FROM %s"),
                     row(list(set(1), set(3))));
          assertRows(execute("SELECT [{min(ck)}, ({max(ck)})] FROM %s"),
                     row(list(set(1), set(3))));
          assertRows(execute("SELECT [{pk}, {ck}] FROM %s"),
                     row(list(set(1), set(1))),
                     row(list(set(1), set(2))),
                     row(list(set(1), set(3))));
          assertRows(execute("SELECT [{pk}, {ck}] FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(list(set(1), set(3))),
                     row(list(set(1), set(2))),
                     row(list(set(1), set(1))));
  
          // Test Maps nested within Lists
          assertRows(execute("SELECT [{}, (map<text, int>){'min' : min(ck), 'max' : max(ck)}] FROM %s"),
                     row(list(map(), map("min", 1, "max", 3))));
          assertRows(execute("SELECT [{}, (map<text, bigint>){'pk' : CAST(pk AS BIGINT), 'ck' : CAST(ck AS BIGINT), 'writetime' : WRITETIME(t)}] FROM %s"),
                     row(list(map(), map("pk", 1L, "ck", 1L, "writetime", timestampInMicros))),
                     row(list(map(), map("pk", 1L, "ck", 2L, "writetime", timestampInMicros))),
                     row(list(map(), map("pk", 1L, "ck", 3L, "writetime", timestampInMicros))));
          assertRows(execute("SELECT [{}, (map<text, int>){'pk' : pk, 'ck' : ck}] FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(list(map(), map("pk", 1, "ck", 3))),
                     row(list(map(), map("pk", 1, "ck", 2))),
                     row(list(map(), map("pk", 1, "ck", 1))));
  
          // Test Tuples nested within Lists
          assertRows(execute("SELECT [(pk, ck, WRITETIME(t))] FROM %s"),
                     row(list(tuple(1, 1, timestampInMicros))),
                     row(list(tuple(1, 2, timestampInMicros))),
                     row(list(tuple(1, 3, timestampInMicros))));
          assertRows(execute("SELECT [(min(ck), max(ck))] FROM %s"),
                     row(list(tuple(1, 3))));
          assertRows(execute("SELECT [(CAST(pk AS BIGINT), CAST(ck AS BIGINT)), (t, WRITETIME(t))] FROM %s"),
                     row(list(tuple(1L, 1L), tuple("one", timestampInMicros))),
                     row(list(tuple(1L, 2L), tuple("two", timestampInMicros))),
                     row(list(tuple(1L, 3L), tuple("three", timestampInMicros))));
  
          // Test UDTs nested within Lists
          String type = createType("CREATE TYPE %s(a int, b int, c bigint)");
          assertRows(execute("SELECT [(" + type + "){a : min(ck), b: max(ck)}] FROM %s"),
                     row(list(userType("a", 1, "b", 3, "c", null))));
          assertRows(execute("SELECT [(" + type + "){a : pk, b : ck, c : WRITETIME(t)}] FROM %s"),
                     row(list(userType("a", 1, "b", 1, "c", timestampInMicros))),
                     row(list(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(list(userType("a", 1, "b", 3, "c", timestampInMicros))));
          assertRows(execute("SELECT [(" + type + "){a : pk, b : ck, c : WRITETIME(t)}] FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(list(userType("a", 1, "b", 3, "c", timestampInMicros))),
                     row(list(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(list(userType("a", 1, "b", 1, "c", timestampInMicros))));
  
          // Test Lists nested within Sets
          assertRows(execute("SELECT {[], [min(ck), max(ck)]} FROM %s"),
                     row(set(list(), list(1, 3))));
          assertRows(execute("SELECT {[], [pk, ck]} FROM %s LIMIT 2"),
                     row(set(list(), list(1, 1))),
                     row(set(list(), list(1, 2))));
          assertRows(execute("SELECT {[], [pk, ck]} FROM %s WHERE pk = 1 ORDER BY ck DESC LIMIT 2"),
                     row(set(list(), list(1, 3))),
                     row(set(list(), list(1, 2))));
          assertRows(execute("SELECT {[min(ck)], ([max(ck)])} FROM %s"),
                     row(set(list(1), list(3))));
          assertRows(execute("SELECT {[pk], ([ck])} FROM %s"),
                     row(set(list(1), list(1))),
                     row(set(list(1), list(2))),
                     row(set(list(1), list(3))));
          assertRows(execute("SELECT {([min(ck)]), [max(ck)]} FROM %s"),
                     row(set(list(1), list(3))));
  
          // Test Sets nested within Sets
          assertRows(execute("SELECT {{}, {min(ck), max(ck)}} FROM %s"),
                     row(set(set(), set(1, 3))));
          assertRows(execute("SELECT {{}, {pk, ck}} FROM %s LIMIT 2"),
                     row(set(set(), set(1, 1))),
                     row(set(set(), set(1, 2))));
          assertRows(execute("SELECT {{}, {pk, ck}} FROM %s WHERE pk = 1 ORDER BY ck DESC LIMIT 2"),
                     row(set(set(), set(1, 3))),
                     row(set(set(), set(1, 2))));
          assertRows(execute("SELECT {{min(ck)}, ({max(ck)})} FROM %s"),
                     row(set(set(1), set(3))));
          assertRows(execute("SELECT {{pk}, ({ck})} FROM %s"),
                     row(set(set(1), set(1))),
                     row(set(set(1), set(2))),
                     row(set(set(1), set(3))));
          assertRows(execute("SELECT {({min(ck)}), {max(ck)}} FROM %s"),
                     row(set(set(1), set(3))));
  
          // Test Maps nested within Sets
          assertRows(execute("SELECT {{}, (map<text, int>){'min' : min(ck), 'max' : max(ck)}} FROM %s"),
                     row(set(map(), map("min", 1, "max", 3))));
          assertRows(execute("SELECT {{}, (map<text, int>){'pk' : pk, 'ck' : ck}} FROM %s"),
                     row(set(map(), map("pk", 1, "ck", 1))),
                     row(set(map(), map("pk", 1, "ck", 2))),
                     row(set(map(), map("pk", 1, "ck", 3))));
  
          // Test Tuples nested within Sets
          assertRows(execute("SELECT {(pk, ck, WRITETIME(t))} FROM %s"),
                     row(set(tuple(1, 1, timestampInMicros))),
                     row(set(tuple(1, 2, timestampInMicros))),
                     row(set(tuple(1, 3, timestampInMicros))));
          assertRows(execute("SELECT {(min(ck), max(ck))} FROM %s"),
                     row(set(tuple(1, 3))));
  
          // Test UDTs nested within Sets
          assertRows(execute("SELECT {(" + type + "){a : min(ck), b: max(ck)}} FROM %s"),
                     row(set(userType("a", 1, "b", 3, "c", null))));
          assertRows(execute("SELECT {(" + type + "){a : pk, b : ck, c : WRITETIME(t)}} FROM %s"),
                     row(set(userType("a", 1, "b", 1, "c", timestampInMicros))),
                     row(set(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(set(userType("a", 1, "b", 3, "c", timestampInMicros))));
          assertRows(execute("SELECT {(" + type + "){a : pk, b : ck, c : WRITETIME(t)}} FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(set(userType("a", 1, "b", 3, "c", timestampInMicros))),
                     row(set(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(set(userType("a", 1, "b", 1, "c", timestampInMicros))));
  
          // Test Lists nested within Maps
          assertRows(execute("SELECT (map<frozen<list<int>>, frozen<list<int>>>){[min(ck)]:[max(ck)]} FROM %s"),
                     row(map(list(1), list(3))));
          assertRows(execute("SELECT (map<frozen<list<int>>, frozen<list<int>>>){[pk]: [ck]} FROM %s"),
                     row(map(list(1), list(1))),
                     row(map(list(1), list(2))),
                     row(map(list(1), list(3))));
  
          // Test Sets nested within Maps
          assertRows(execute("SELECT (map<frozen<set<int>>, frozen<set<int>>>){{min(ck)} : {max(ck)}} FROM %s"),
                     row(map(set(1), set(3))));
          assertRows(execute("SELECT (map<frozen<set<int>>, frozen<set<int>>>){{pk} : {ck}} FROM %s"),
                     row(map(set(1), set(1))),
                     row(map(set(1), set(2))),
                     row(map(set(1), set(3))));
  
          // Test Maps nested within Maps
          assertRows(execute("SELECT (map<frozen<map<text, int>>, frozen<map<text, int>>>){{'min' : min(ck)} : {'max' : max(ck)}} FROM %s"),
                     row(map(map("min", 1), map("max", 3))));
          assertRows(execute("SELECT (map<frozen<map<text, int>>, frozen<map<text, int>>>){{'pk' : pk} : {'ck' : ck}} FROM %s"),
                     row(map(map("pk", 1), map("ck", 1))),
                     row(map(map("pk", 1), map("ck", 2))),
                     row(map(map("pk", 1), map("ck", 3))));
  
          // Test Tuples nested within Maps
          assertRows(execute("SELECT (map<frozen<tuple<int, int>>, frozen<tuple<bigint>>>){(pk, ck) : (WRITETIME(t))} FROM %s"),
                     row(map(tuple(1, 1), tuple(timestampInMicros))),
                     row(map(tuple(1, 2), tuple(timestampInMicros))),
                     row(map(tuple(1, 3), tuple(timestampInMicros))));
          assertRows(execute("SELECT (map<frozen<tuple<int>> , frozen<tuple<int>>>){(min(ck)) : (max(ck))} FROM %s"),
                     row(map(tuple(1), tuple(3))));
  
          // Test UDTs nested within Maps
          assertRows(execute("SELECT (map<int, frozen<" + type + ">>){ck : {a : min(ck), b: max(ck)}} FROM %s"),
                     row(map(1, userType("a", 1, "b", 3, "c", null))));
          assertRows(execute("SELECT (map<int, frozen<" + type + ">>){ck : {a : pk, b : ck, c : WRITETIME(t)}} FROM %s"),
                     row(map(1, userType("a", 1, "b", 1, "c", timestampInMicros))),
                     row(map(2, userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(map(3, userType("a", 1, "b", 3, "c", timestampInMicros))));
          assertRows(execute("SELECT (map<int, frozen<" + type + ">>){ck : {a : pk, b : ck, c : WRITETIME(t)}} FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(map(3, userType("a", 1, "b", 3, "c", timestampInMicros))),
                     row(map(2, userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(map(1, userType("a", 1, "b", 1, "c", timestampInMicros))));
  
          // Test Lists nested within Tuples
          assertRows(execute("SELECT ([min(ck)], [max(ck)]) FROM %s"),
                     row(tuple(list(1), list(3))));
          assertRows(execute("SELECT ([pk], [ck]) FROM %s"),
                     row(tuple(list(1), list(1))),
                     row(tuple(list(1), list(2))),
                     row(tuple(list(1), list(3))));
  
          // Test Sets nested within Tuples
          assertRows(execute("SELECT ({min(ck)}, {max(ck)}) FROM %s"),
                     row(tuple(set(1), set(3))));
          assertRows(execute("SELECT ({pk}, {ck}) FROM %s"),
                     row(tuple(set(1), set(1))),
                     row(tuple(set(1), set(2))),
                     row(tuple(set(1), set(3))));
  
          // Test Maps nested within Tuples
          assertRows(execute("SELECT ((map<text, int>){'min' : min(ck)}, (map<text, int>){'max' : max(ck)}) FROM %s"),
                     row(tuple(map("min", 1), map("max", 3))));
          assertRows(execute("SELECT ((map<text, int>){'pk' : pk}, (map<text, int>){'ck' : ck}) FROM %s"),
                     row(tuple(map("pk", 1), map("ck", 1))),
                     row(tuple(map("pk", 1), map("ck", 2))),
                     row(tuple(map("pk", 1), map("ck", 3))));
  
          // Test Tuples nested within Tuples
          assertRows(execute("SELECT (tuple<tuple<int, int, bigint>>)((pk, ck, WRITETIME(t))) FROM %s"),
                     row(tuple(tuple(1, 1, timestampInMicros))),
                     row(tuple(tuple(1, 2, timestampInMicros))),
                     row(tuple(tuple(1, 3, timestampInMicros))));
          assertRows(execute("SELECT (tuple<tuple<int, int, bigint>>)((min(ck), max(ck))) FROM %s"),
                     row(tuple(tuple(1, 3))));
  
          assertRows(execute("SELECT ((t, WRITETIME(t)), (CAST(pk AS BIGINT), CAST(ck AS BIGINT))) FROM %s"),
                     row(tuple(tuple("one", timestampInMicros), tuple(1L, 1L))),
                     row(tuple(tuple("two", timestampInMicros), tuple(1L, 2L))),
                     row(tuple(tuple("three", timestampInMicros), tuple(1L, 3L))));
  
          // Test UDTs nested within Tuples
          assertRows(execute("SELECT (tuple<" + type + ">)({a : min(ck), b: max(ck)}) FROM %s"),
                     row(tuple(userType("a", 1, "b", 3, "c", null))));
          assertRows(execute("SELECT (tuple<" + type + ">)({a : pk, b : ck, c : WRITETIME(t)}) FROM %s"),
                     row(tuple(userType("a", 1, "b", 1, "c", timestampInMicros))),
                     row(tuple(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(tuple(userType("a", 1, "b", 3, "c", timestampInMicros))));
          assertRows(execute("SELECT (tuple<" + type + ">)({a : pk, b : ck, c : WRITETIME(t)}) FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(tuple(userType("a", 1, "b", 3, "c", timestampInMicros))),
                     row(tuple(userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(tuple(userType("a", 1, "b", 1, "c", timestampInMicros))));
  
          // Test Lists nested within UDTs
          String containerType = createType("CREATE TYPE %s(l list<int>)");
          assertRows(execute("SELECT (" + containerType + "){l : [min(ck), max(ck)]} FROM %s"),
                     row(userType("l", list(1, 3))));
          assertRows(execute("SELECT (" + containerType + "){l : [pk, ck]} FROM %s"),
                     row(userType("l", list(1, 1))),
                     row(userType("l", list(1, 2))),
                     row(userType("l", list(1, 3))));
  
          // Test Sets nested within UDTs
          containerType = createType("CREATE TYPE %s(s set<int>)");
          assertRows(execute("SELECT (" + containerType + "){s : {min(ck), max(ck)}} FROM %s"),
                     row(userType("s", set(1, 3))));
          assertRows(execute("SELECT (" + containerType + "){s : {pk, ck}} FROM %s"),
                     row(userType("s", set(1))),
                     row(userType("s", set(1, 2))),
                     row(userType("s", set(1, 3))));
  
          // Test Maps nested within UDTs
          containerType = createType("CREATE TYPE %s(m map<text, int>)");
          assertRows(execute("SELECT (" + containerType + "){m : {'min' : min(ck), 'max' : max(ck)}} FROM %s"),
                     row(userType("m", map("min", 1, "max", 3))));
          assertRows(execute("SELECT (" + containerType + "){m : {'pk' : pk, 'ck' : ck}} FROM %s"),
                     row(userType("m", map("pk", 1, "ck", 1))),
                     row(userType("m", map("pk", 1, "ck", 2))),
                     row(userType("m", map("pk", 1, "ck", 3))));
  
          // Test Tuples nested within UDTs
          containerType = createType("CREATE TYPE %s(t tuple<int, int>, w tuple<bigint>)");
          assertRows(execute("SELECT (" + containerType + "){t : (pk, ck), w : (WRITETIME(t))} FROM %s"),
                     row(userType("t", tuple(1, 1), "w", tuple(timestampInMicros))),
                     row(userType("t", tuple(1, 2), "w", tuple(timestampInMicros))),
                     row(userType("t", tuple(1, 3), "w", tuple(timestampInMicros))));
  
          // Test UDTs nested within Maps
          containerType = createType("CREATE TYPE %s(t frozen<" + type + ">)");
          assertRows(execute("SELECT (" + containerType + "){t : {a : min(ck), b: max(ck)}} FROM %s"),
                     row(userType("t", userType("a", 1, "b", 3, "c", null))));
          assertRows(execute("SELECT (" + containerType + "){t : {a : pk, b : ck, c : WRITETIME(t)}} FROM %s"),
                     row(userType("t", userType("a", 1, "b", 1, "c", timestampInMicros))),
                     row(userType("t", userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(userType("t", userType("a", 1, "b", 3, "c", timestampInMicros))));
          assertRows(execute("SELECT (" + containerType + "){t : {a : pk, b : ck, c : WRITETIME(t)}} FROM %s WHERE pk = 1 ORDER BY ck DESC"),
                     row(userType("t", userType("a", 1, "b", 3, "c", timestampInMicros))),
                     row(userType("t", userType("a", 1, "b", 2, "c", timestampInMicros))),
                     row(userType("t", userType("a", 1, "b", 1, "c", timestampInMicros))));
  
  
          // Test Litteral Set with Duration elements
          assertInvalidMessage("Durations are not allowed inside sets: set<duration>",
                               "SELECT pk, ck, (set<duration>){2d, 1mo} FROM %s");
  
          assertInvalidMessage("Invalid field selection: system.min(ck) of type int is not a user type",
                               "SELECT min(ck).min FROM %s");
          assertInvalidMessage("Invalid field selection: (map<text, int>){'min': system.min(ck), 'max': system.max(ck)} of type frozen<map<text, int>> is not a user type",
                               "SELECT (map<text, int>) {'min' : min(ck), 'max' : max(ck)}.min FROM %s");
      }
  
      @Test
      public void testCollectionLiteralsWithDurations() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck int, d1 duration, d2 duration, PRIMARY KEY (pk, ck) )");
          execute("INSERT INTO %s (pk, ck, d1, d2) VALUES (1, 1, 15h, 13h)");
          execute("INSERT INTO %s (pk, ck, d1, d2) VALUES (1, 2, 10h, 12h)");
          execute("INSERT INTO %s (pk, ck, d1, d2) VALUES (1, 3, 11h, 13h)");
  
          assertRows(execute("SELECT [d1, d2] FROM %s"),
                     row(list(Duration.from("15h"), Duration.from("13h"))),
                     row(list(Duration.from("10h"), Duration.from("12h"))),
                     row(list(Duration.from("11h"), Duration.from("13h"))));
  
          assertInvalidMessage("Durations are not allowed inside sets: frozen<set<duration>>", "SELECT {d1, d2} FROM %s");
  
          assertRows(execute("SELECT (map<int, duration>){ck : d1} FROM %s"),
                     row(map(1, Duration.from("15h"))),
                     row(map(2, Duration.from("10h"))),
                     row(map(3, Duration.from("11h"))));
  
          assertInvalidMessage("Durations are not allowed as map keys: map<duration, int>",
                               "SELECT (map<duration, int>){d1 : ck, d2 :ck} FROM %s");
      }
  
      @Test
      public void testSelectUDTLiteral() throws Throwable
      {
          String type = createType("CREATE TYPE %s(a int, b text)");
          createTable("CREATE TABLE %s (k int PRIMARY KEY, v " + type + ")");
  
          execute("INSERT INTO %s(k, v) VALUES (?, ?)", 0, userType("a", 3, "b", "foo"));
  
          assertInvalidMessage("Cannot infer type for term", "SELECT { a: 4, b: 'bar'} FROM %s");
  
          assertRows(execute("SELECT k, v, (" + type + "){ a: 4, b: 'bar'} FROM %s"),
              row(0, userType("a", 3, "b", "foo"), userType("a", 4, "b", "bar"))
          );
  
          assertRows(execute("SELECT k, v, (" + type + ")({ a: 4, b: 'bar'}) FROM %s"),
              row(0, userType("a", 3, "b", "foo"), userType("a", 4, "b", "bar"))
          );
  
          assertRows(execute("SELECT k, v, ((" + type + "){ a: 4, b: 'bar'}).a FROM %s"),
                     row(0, userType("a", 3, "b", "foo"), 4)
          );
  
          assertRows(execute("SELECT k, v, (" + type + "){ a: 4, b: 'bar'}.a FROM %s"),
                     row(0, userType("a", 3, "b", "foo"), 4)
          );
  
          assertInvalidMessage("Cannot infer type for term", "SELECT { a: 4} FROM %s");
  
          assertRows(execute("SELECT k, v, (" + type + "){ a: 4} FROM %s"),
              row(0, userType("a", 3, "b", "foo"), userType("a", 4, "b", null))
          );
  
          assertRows(execute("SELECT k, v, (" + type + "){ b: 'bar'} FROM %s"),
                     row(0, userType("a", 3, "b", "foo"), userType("a", null, "b", "bar"))
          );
  
          execute("INSERT INTO %s(k, v) VALUES (?, ?)", 1, userType("a", 5, "b", "foo"));
          assertRows(execute("SELECT (" + type + "){ a: max(v.a) , b: 'max'} FROM %s"),
                     row(userType("a", 5, "b", "max"))
          );
          assertRows(execute("SELECT (" + type + "){ a: min(v.a) , b: 'min'} FROM %s"),
                     row(userType("a", 3, "b", "min"))
          );
      }
  
      @Test
      public void testInvalidSelect() throws Throwable
      {
          // Creates a table just so we can reference it in the (invalid) SELECT below
          createTable("CREATE TABLE %s (k int PRIMARY KEY)");
  
          assertInvalidMessage("Cannot infer type for term", "SELECT ? FROM %s");
          assertInvalidMessage("Cannot infer type for term", "SELECT k, ? FROM %s");
  
          assertInvalidMessage("Cannot infer type for term", "SELECT k, null FROM %s");
      }
  
      private void assertColumnSpec(ColumnSpecification spec, String expectedName, AbstractType<?> expectedType)
      {
          assertEquals(expectedName, spec.name.toString());
          assertEquals(expectedType, spec.type);
      }
  
      @Test
      public void testSelectPrepared() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck int, t text, PRIMARY KEY (pk, ck) )");
          execute("INSERT INTO %s (pk, ck, t) VALUES (1, 1, 'one')");
          execute("INSERT INTO %s (pk, ck, t) VALUES (1, 2, 'two')");
          execute("INSERT INTO %s (pk, ck, t) VALUES (1, 3, 'three')");
  
          String query = "SELECT (int)?, (decimal):adecimal, (text)?, (tuple<int,text>):atuple, pk, ck, t FROM %s WHERE pk = ?";
          ResultMessage.Prepared prepared = prepare(query);
  
          List<ColumnSpecification> boundNames = prepared.metadata.names;
  
          // 5 bound variables
          assertEquals(5, boundNames.size());
          assertColumnSpec(boundNames.get(0), "[selection]", Int32Type.instance);
          assertColumnSpec(boundNames.get(1), "adecimal", DecimalType.instance);
          assertColumnSpec(boundNames.get(2), "[selection]", UTF8Type.instance);
          assertColumnSpec(boundNames.get(3), "atuple", TypeParser.parse("TupleType(Int32Type,UTF8Type)"));
          assertColumnSpec(boundNames.get(4), "pk", Int32Type.instance);
  
  
          List<ColumnSpecification> resultNames = prepared.resultMetadata.names;
  
          // 7 result "columns"
          assertEquals(7, resultNames.size());
          assertColumnSpec(resultNames.get(0), "(int)?", Int32Type.instance);
          assertColumnSpec(resultNames.get(1), "(decimal)?", DecimalType.instance);
          assertColumnSpec(resultNames.get(2), "(text)?", UTF8Type.instance);
          assertColumnSpec(resultNames.get(3), "(tuple<int, text>)?", TypeParser.parse("TupleType(Int32Type,UTF8Type)"));
          assertColumnSpec(resultNames.get(4), "pk", Int32Type.instance);
          assertColumnSpec(resultNames.get(5), "ck", Int32Type.instance);
          assertColumnSpec(resultNames.get(6), "t", UTF8Type.instance);
  
          assertRows(execute(query, 88, BigDecimal.TEN, "foo bar baz", tuple(42, "ursus"), 1),
                     row(88, BigDecimal.TEN, "foo bar baz", tuple(42, "ursus"),
                         1, 1, "one"),
                     row(88, BigDecimal.TEN, "foo bar baz", tuple(42, "ursus"),
                         1, 2, "two"),
                     row(88, BigDecimal.TEN, "foo bar baz", tuple(42, "ursus"),
                         1, 3, "three"));
      }
  
      @Test
      public void testConstantFunctionArgs() throws Throwable
      {
          String fInt = createFunction(KEYSPACE,
                                       "int,int",
                                       "CREATE FUNCTION %s (val1 int, val2 int) " +
                                       "CALLED ON NULL INPUT " +
                                       "RETURNS int " +
                                       "LANGUAGE java\n" +
                                       "AS 'return Math.max(val1, val2);';");
          String fFloat = createFunction(KEYSPACE,
                                         "float,float",
                                         "CREATE FUNCTION %s (val1 float, val2 float) " +
                                         "CALLED ON NULL INPUT " +
                                         "RETURNS float " +
                                         "LANGUAGE java\n" +
                                         "AS 'return Math.max(val1, val2);';");
          String fText = createFunction(KEYSPACE,
                                        "text,text",
                                        "CREATE FUNCTION %s (val1 text, val2 text) " +
                                        "CALLED ON NULL INPUT " +
                                        "RETURNS text " +
                                        "LANGUAGE java\n" +
                                        "AS 'return val2;';");
          String fAscii = createFunction(KEYSPACE,
                                         "ascii,ascii",
                                         "CREATE FUNCTION %s (val1 ascii, val2 ascii) " +
                                         "CALLED ON NULL INPUT " +
                                         "RETURNS ascii " +
                                         "LANGUAGE java\n" +
                                         "AS 'return val2;';");
          String fTimeuuid = createFunction(KEYSPACE,
                                            "timeuuid,timeuuid",
                                            "CREATE FUNCTION %s (val1 timeuuid, val2 timeuuid) " +
                                            "CALLED ON NULL INPUT " +
                                            "RETURNS timeuuid " +
                                            "LANGUAGE java\n" +
                                            "AS 'return val2;';");
  
          createTable("CREATE TABLE %s (pk int PRIMARY KEY, valInt int, valFloat float, valText text, valAscii ascii, valTimeuuid timeuuid)");
          execute("INSERT INTO %s (pk, valInt, valFloat, valText, valAscii, valTimeuuid) " +
                  "VALUES (1, 10, 10.0, '100', '100', 2deb23e0-96b5-11e5-b26d-a939dd1405a3)");
  
          assertRows(execute("SELECT pk, " + fInt + "(valInt, 100) FROM %s"),
                     row(1, 100));
          assertRows(execute("SELECT pk, " + fInt + "(valInt, (int)100) FROM %s"),
                     row(1, 100));
          assertInvalidMessage("Type error: (bigint)100 cannot be passed as argument 1 of function",
                               "SELECT pk, " + fInt + "(valInt, (bigint)100) FROM %s");
          assertRows(execute("SELECT pk, " + fFloat + "(valFloat, (float)100.00) FROM %s"),
                     row(1, 100f));
          assertRows(execute("SELECT pk, " + fText + "(valText, 'foo') FROM %s"),
                     row(1, "foo"));
          assertRows(execute("SELECT pk, " + fAscii + "(valAscii, (ascii)'foo') FROM %s"),
                     row(1, "foo"));
          assertRows(execute("SELECT pk, " + fTimeuuid + "(valTimeuuid, (timeuuid)34617f80-96b5-11e5-b26d-a939dd1405a3) FROM %s"),
                     row(1, UUID.fromString("34617f80-96b5-11e5-b26d-a939dd1405a3")));
  
          // ambiguous
  
          String fAmbiguousFunc1 = createFunction(KEYSPACE,
                                                  "int,bigint",
                                                  "CREATE FUNCTION %s (val1 int, val2 bigint) " +
                                                  "CALLED ON NULL INPUT " +
                                                  "RETURNS bigint " +
                                                  "LANGUAGE java\n" +
                                                  "AS 'return Math.max((long)val1, val2);';");
          assertRows(execute("SELECT pk, " + fAmbiguousFunc1 + "(valInt, 100) FROM %s"),
                     row(1, 100L));
          createFunctionOverload(fAmbiguousFunc1, "int,int",
                                                  "CREATE FUNCTION %s (val1 int, val2 int) " +
                                                  "CALLED ON NULL INPUT " +
                                                  "RETURNS int " +
                                                  "LANGUAGE java\n" +
                                                  "AS 'return Math.max(val1, val2);';");
          assertRows(execute("SELECT pk, " + fAmbiguousFunc1 + "(valInt, 100) FROM %s"),
                     row(1, 100));
      }
  
      @Test
      public void testPreparedFunctionArgs() throws Throwable
      {
          createTable("CREATE TABLE %s (pk int, ck int, t text, i int, PRIMARY KEY (pk, ck) )");
          execute("INSERT INTO %s (pk, ck, t, i) VALUES (1, 1, 'one', 50)");
          execute("INSERT INTO %s (pk, ck, t, i) VALUES (1, 2, 'two', 100)");
          execute("INSERT INTO %s (pk, ck, t, i) VALUES (1, 3, 'three', 150)");
  
          String fIntMax = createFunction(KEYSPACE,
                                          "int,int",
                                          "CREATE FUNCTION %s (val1 int, val2 int) " +
                                          "CALLED ON NULL INPUT " +
                                          "RETURNS int " +
                                          "LANGUAGE java\n" +
                                          "AS 'return Math.max(val1, val2);';");
  
          // weak typing
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s", 0),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s", 100),
                     row(1, 1, 100),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s", 200),
                     row(1, 1, 200),
                     row(1, 2, 200),
                     row(1, 3, 200));
  
          // explicit typing
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s", 0),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s", 100),
                     row(1, 1, 100),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s", 200),
                     row(1, 1, 200),
                     row(1, 2, 200),
                     row(1, 3, 200));
  
          // weak typing
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s WHERE pk = " + fIntMax + "(1,1)", 0),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s WHERE pk = " + fIntMax + "(2,1)", 0));
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s WHERE pk = " + fIntMax + "(?,1)", 0, 1),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, ?) FROM %s WHERE pk = " + fIntMax + "(?,1)", 0, 2));
  
          // explicit typing
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s WHERE pk = " + fIntMax + "((int)1,(int)1)", 0),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s WHERE pk = " + fIntMax + "((int)2,(int)1)", 0));
  
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s WHERE pk = " + fIntMax + "((int)?,(int)1)", 0, 1),
                     row(1, 1, 50),
                     row(1, 2, 100),
                     row(1, 3, 150));
          assertRows(execute("SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s WHERE pk = " + fIntMax + "((int)?,(int)1)", 0, 2));
  
          assertInvalidMessage("Invalid unset value for argument", "SELECT pk, ck, " + fIntMax + "(i, (int)?) FROM %s WHERE pk = " + fIntMax + "((int)1,(int)1)", unset());
      }
  
      @Test
      public void testInsertUpdateDelete() throws Throwable
      {
          String fIntMax = createFunction(KEYSPACE,
                                          "int,int",
                                          "CREATE FUNCTION %s (val1 int, val2 int) " +
                                          "CALLED ON NULL INPUT " +
                                          "RETURNS int " +
                                          "LANGUAGE java\n" +
                                          "AS 'return Math.max(val1, val2);';");
  
          createTable("CREATE TABLE %s (pk int, ck int, t text, i int, PRIMARY KEY (pk, ck) )");
  
          execute("UPDATE %s SET i = " + fIntMax + "(100, 200) WHERE pk = 1 AND ck = 1");
          assertRows(execute("SELECT i FROM %s WHERE pk = 1 AND ck = 1"),
                     row(200));
  
          execute("UPDATE %s SET i = " + fIntMax + "(100, 300) WHERE pk = 1 AND ck = " + fIntMax + "(1,2)");
          assertRows(execute("SELECT i FROM %s WHERE pk = 1 AND ck = 2"),
                     row(300));
  
          execute("DELETE FROM %s WHERE pk = 1 AND ck = " + fIntMax + "(1,2)");
          assertRows(execute("SELECT i FROM %s WHERE pk = 1 AND ck = 2"));
  
          execute("INSERT INTO %s (pk, ck, i) VALUES (1, " + fIntMax + "(1,2), " + fIntMax + "(100, 300))");
          assertRows(execute("SELECT i FROM %s WHERE pk = 1 AND ck = 2"),
                     row(300));
      }
  }
  