# 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.

import pytest

from tests.common.impala_test_suite import ImpalaTestSuite
from tests.common.test_dimensions import create_exec_option_dimension

class TestStringQueries(ImpalaTestSuite):
  @classmethod
  def get_workload(cls):
    return 'functional-query'

  def setup_method(self, method):
    self.__cleanup_char_tables()
    self.__create_char_tables()

  def teardown_method(self, method):
    self.__cleanup_char_tables()

  def __cleanup_char_tables(self):
    self.client.execute('drop table if exists functional.test_char_tmp');
    self.client.execute('drop table if exists functional.test_varchar_tmp');
    self.client.execute('drop table if exists functional.allchars');
    self.client.execute('drop table if exists functional.allchars_par');
    self.client.execute('drop table if exists functional.test_char_nulls');

  def __create_char_tables(self):
    self.client.execute(
        'create table if not exists ' +
        'functional.test_varchar_tmp (vc varchar(5))')
    self.client.execute(
        'create table if not exists functional.test_char_tmp (c char(5))')
    self.client.execute(
        'create table if not exists functional.allchars ' +
        '(cshort char(5), clong char(140), vc varchar(5))')
    self.client.execute(
        'create table if not exists functional.allchars_par ' +
        '(cshort char(5), clong char(140), vc varchar(5)) stored as parquet')

    # Regression test for IMPALA-1339
    self.client.execute('create table if not exists ' +
        '''functional.test_char_nulls ( c20 char(20),
                                        c40 char(40),
                                        c60 char(60),
                                        c80 char(80),
                                        c81 char(81),
                                        c82 char(82),
                                        c100 char(100),
                                        c120 char(120),
                                        c140 char(140))''')
    self.client.execute('insert into functional.test_char_nulls ' +
        'values (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)');
    self.client.execute('insert into functional.test_char_nulls ' +
        'values (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)');

  @classmethod
  def add_test_dimensions(cls):
    super(TestStringQueries, cls).add_test_dimensions()
    cls.ImpalaTestMatrix.add_dimension(
      create_exec_option_dimension(disable_codegen_options=[False, True]))
    cls.ImpalaTestMatrix.add_constraint(lambda v:\
        v.get_value('table_format').file_format in ['text'] and
        v.get_value('table_format').compression_codec in ['none'])

  @pytest.mark.execute_serially
  def test_varchar(self, vector):
    self.run_test_case('QueryTest/chars', vector)

class TestCharFormats(ImpalaTestSuite):
  @classmethod
  def get_workload(cls):
    return 'functional-query'

  def setup_method(self, method):
    self.__create_char_tables()

  def __create_char_tables(self):
    self.client.execute('''create external table if not exists
        functional_parquet.chars_formats
        (cs CHAR(5), cl CHAR(140), vc VARCHAR(32))
        STORED AS PARQUET
        LOCATION "/test-warehouse/chars_formats_parquet"''')
    self.client.execute('''create external table if not exists
        functional.chars_formats
        (cs CHAR(5), cl CHAR(140), vc VARCHAR(32))
        ROW FORMAT delimited fields terminated by ','  escaped by '\\\\'
        STORED AS TEXTFILE
        LOCATION "/test-warehouse/chars_formats_text"
        ''')
    self.client.execute('''create external table if not exists
        functional_avro_snap.chars_formats
        (cs CHAR(5), cl CHAR(140), vc VARCHAR(32))
        STORED AS AVRO
        LOCATION "/test-warehouse/chars_formats_avro_snap"
        TBLPROPERTIES ('avro.schema.literal'='{"type":"record",
        "name":"CharTypesTest","doc":"Schema generated by Kite",
        "fields":[
        {"name":"cs","type":["null","string"], "doc":"Type inferred"},
        {"name":"cl","type":["null","string"], "doc":"Type inferred"},
        {"name":"vc","type":["null","string"],"doc":"Type inferred"}]}')''')

  @classmethod
  def add_test_dimensions(cls):
    super(TestCharFormats, cls).add_test_dimensions()
    cls.ImpalaTestMatrix.add_dimension(
      create_exec_option_dimension(disable_codegen_options=[False, True]))
    cls.ImpalaTestMatrix.add_constraint(lambda v:
        (v.get_value('table_format').file_format in ['avro'] and
        v.get_value('table_format').compression_codec in ['snap']) or
        v.get_value('table_format').file_format in ['parquet'] or
        (v.get_value('table_format').file_format in ['text'] and
        v.get_value('table_format').compression_codec in ['none']))

  def test_char_format(self, vector):
    self.run_test_case('QueryTest/chars-formats', vector)
