/*
 * 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.beam.sdk.extensions.sql.meta.provider.hcatalog;

import static org.apache.beam.sdk.io.hcatalog.test.HCatalogIOTestUtils.TEST_DATABASE;
import static org.apache.beam.sdk.io.hcatalog.test.HCatalogIOTestUtils.TEST_RECORDS_COUNT;
import static org.apache.beam.sdk.io.hcatalog.test.HCatalogIOTestUtils.TEST_TABLE;
import static org.apache.beam.sdk.io.hcatalog.test.HCatalogIOTestUtils.getExpectedRecordsAsKV;
import static org.apache.beam.sdk.io.hcatalog.test.HCatalogIOTestUtils.insertTestData;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.beam.sdk.extensions.sql.SqlTransform;
import org.apache.beam.sdk.extensions.sql.impl.schema.BeamPCollectionTable;
import org.apache.beam.sdk.extensions.sql.meta.provider.ReadOnlyTableProvider;
import org.apache.beam.sdk.extensions.sql.meta.provider.TableProvider;
import org.apache.beam.sdk.io.hcatalog.test.EmbeddedMetastoreService;
import org.apache.beam.sdk.schemas.Schema;
import org.apache.beam.sdk.testing.PAssert;
import org.apache.beam.sdk.testing.TestPipeline;
import org.apache.beam.sdk.transforms.Create;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.PTransform;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.values.KV;
import org.apache.beam.sdk.values.PBegin;
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.values.Row;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableMap;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

/** Test for HCatalogTableProvider. */
public class BeamSqlHiveSchemaTest implements Serializable {

  private static final Schema ROW_SCHEMA =
      Schema.builder().addInt32Field("f_int").addStringField("f_string").build();

  @ClassRule public static final TemporaryFolder TMP_FOLDER = new TemporaryFolder();

  @Rule public final transient TestPipeline defaultPipeline = TestPipeline.create();

  @Rule public final transient TestPipeline readAfterWritePipeline = TestPipeline.create();

  @Rule public final TestPipeline pipeline = TestPipeline.create();

  private static EmbeddedMetastoreService service;

  @BeforeClass
  public static void setupEmbeddedMetastoreService() throws IOException {
    service = new EmbeddedMetastoreService(TMP_FOLDER.getRoot().getAbsolutePath());
  }

  @AfterClass
  public static void shutdownEmbeddedMetastoreService() throws Exception {
    if (service != null) {
      service.executeQuery("drop table " + TEST_TABLE);
      service.close();
    }
  }

  @Test
  public void testSelectFromHCatalog() throws Exception {
    initializeHCatalog();

    PCollection<KV<String, Integer>> output =
        readAfterWritePipeline
            .apply(
                SqlTransform.query(
                        String.format(
                            "SELECT f_str, f_int FROM `hive`.`%s`.`%s`", TEST_DATABASE, TEST_TABLE))
                    .withTableProvider("hive", hiveTableProvider()))
            .apply(ParDo.of(new ToKV()));
    PAssert.that(output).containsInAnyOrder(getExpectedRecordsAsKV(TEST_RECORDS_COUNT));
    readAfterWritePipeline.run();
  }

  @Test
  public void testSelectFromImplicitDefaultDb() throws Exception {
    initializeHCatalog();

    PCollection<KV<String, Integer>> output =
        readAfterWritePipeline
            .apply(
                SqlTransform.query(
                        String.format("SELECT f_str, f_int FROM `hive`.`%s`", TEST_TABLE))
                    .withTableProvider("hive", hiveTableProvider()))
            .apply(ParDo.of(new ToKV()));
    PAssert.that(output).containsInAnyOrder(getExpectedRecordsAsKV(TEST_RECORDS_COUNT));
    readAfterWritePipeline.run();
  }

  @Test
  public void testSelectFromImplicitDefaultSchema() throws Exception {
    initializeHCatalog();

    PCollection<KV<String, Integer>> output =
        readAfterWritePipeline
            .apply(
                SqlTransform.query(
                        String.format(
                            "SELECT f_str, f_int FROM `%s`.`%s`", TEST_DATABASE, TEST_TABLE))
                    .withDefaultTableProvider("hive", hiveTableProvider()))
            .apply(ParDo.of(new ToKV()));
    PAssert.that(output).containsInAnyOrder(getExpectedRecordsAsKV(TEST_RECORDS_COUNT));
    readAfterWritePipeline.run();
  }

  @Test
  public void testSelectFromImplicitDefaultSchemaAndDB() throws Exception {
    initializeHCatalog();

    PCollection<KV<String, Integer>> output =
        readAfterWritePipeline
            .apply(
                SqlTransform.query(String.format("SELECT f_str, f_int FROM `%s`", TEST_TABLE))
                    .withDefaultTableProvider("hive", hiveTableProvider()))
            .apply(ParDo.of(new ToKV()));
    PAssert.that(output).containsInAnyOrder(getExpectedRecordsAsKV(TEST_RECORDS_COUNT));
    readAfterWritePipeline.run();
  }

  @Test
  public void testJoinPCollectionWithHCatalog() throws Exception {
    initializeHCatalog();

    PCollection<Row> inputMain =
        pipeline.apply("pcollection", create(row(1, "pcollection_1"), row(2, "pcollection_2")));

    PCollection<Row> result =
        inputMain.apply(
            SqlTransform.query(
                    "SELECT hive.f_int, (hive.f_str || ' ' || pcollection.f_string) AS f_string \n"
                        + "FROM `hive`.`default`.`mytable` AS hive \n"
                        + "   INNER JOIN \n"
                        + " PCOLLECTION AS pcollection \n"
                        + "   ON pcollection.f_int = hive.f_int")
                .withTableProvider("hive", hiveTableProvider()));

    PAssert.that(result)
        .containsInAnyOrder(row(1, "record 1 pcollection_1"), row(2, "record 2 pcollection_2"));
    pipeline.run();
  }

  @Test
  public void testJoinMultipleExtraProvidersWithMain() throws Exception {
    initializeHCatalog();

    PCollection<Row> inputMain =
        pipeline.apply("mainInput", create(row(1, "pcollection_1"), row(2, "pcollection_2")));

    PCollection<Row> inputExtra =
        pipeline.apply("extraInput", create(row(1, "_extra_table_1"), row(2, "_extra_table_2")));

    PCollection<Row> result =
        inputMain.apply(
            SqlTransform.query(
                    "SELECT \n"
                        + "   x_tbl.f_int as f_int, \n"
                        + "   (p_tbl.f_string || x_tbl.f_string || ' ' || h_tbl.f_str) AS f_string \n"
                        + "FROM \n"
                        + "     `extraSchema`.`extraTable` AS x_tbl \n"
                        + "  INNER JOIN \n"
                        + "     `hive`.`default`.`mytable` AS h_tbl \n"
                        + "        ON h_tbl.f_int = x_tbl.f_int \n"
                        + "  INNER JOIN \n"
                        + "     PCOLLECTION AS p_tbl \n"
                        + "        ON p_tbl.f_int = x_tbl.f_int")
                .withTableProvider("extraSchema", extraTableProvider("extraTable", inputExtra))
                .withTableProvider("hive", hiveTableProvider()));

    PAssert.that(result)
        .containsInAnyOrder(
            row(1, "pcollection_1_extra_table_1 record 1"),
            row(2, "pcollection_2_extra_table_2 record 2"));
    pipeline.run();
  }

  @Test
  public void testJoinMultipleExtraProvidersWithImplicitHiveDB() throws Exception {
    initializeHCatalog();

    PCollection<Row> inputMain =
        pipeline.apply("mainInput", create(row(1, "pcollection_1"), row(2, "pcollection_2")));

    PCollection<Row> inputExtra =
        pipeline.apply("extraInput", create(row(1, "_extra_table_1"), row(2, "_extra_table_2")));

    PCollection<Row> result =
        inputMain.apply(
            SqlTransform.query(
                    "SELECT \n"
                        + "   x_tbl.f_int as f_int, \n"
                        + "   (p_tbl.f_string || x_tbl.f_string || ' ' || h_tbl.f_str) AS f_string \n"
                        + "FROM \n"
                        + "     `extraSchema`.`extraTable` AS x_tbl \n"
                        + "  INNER JOIN \n"
                        + "     `hive`.`mytable` AS h_tbl \n"
                        + "        ON h_tbl.f_int = x_tbl.f_int \n"
                        + "  INNER JOIN \n"
                        + "     PCOLLECTION AS p_tbl \n"
                        + "        ON p_tbl.f_int = x_tbl.f_int")
                .withTableProvider("extraSchema", extraTableProvider("extraTable", inputExtra))
                .withTableProvider("hive", hiveTableProvider()));

    PAssert.that(result)
        .containsInAnyOrder(
            row(1, "pcollection_1_extra_table_1 record 1"),
            row(2, "pcollection_2_extra_table_2 record 2"));
    pipeline.run();
  }

  private void reCreateTestTable() throws Exception {
    service.executeQuery("drop table " + TEST_TABLE);
    service.executeQuery("create table " + TEST_TABLE + "(f_str string, f_int int)");
  }

  private void initializeHCatalog() throws Exception {
    reCreateTestTable();
    insertTestData(service.getHiveConfAsMap());
  }

  private TableProvider hiveTableProvider() {
    return HCatalogTableProvider.create(service.getHiveConfAsMap());
  }

  private Row row(int fIntValue, String fStringValue) {
    return Row.withSchema(ROW_SCHEMA).addValues(fIntValue, fStringValue).build();
  }

  private TableProvider extraTableProvider(String tableName, PCollection<Row> rows) {
    return new ReadOnlyTableProvider(
        "testExtraTableProvider", ImmutableMap.of(tableName, new BeamPCollectionTable<>(rows)));
  }

  private PTransform<PBegin, PCollection<Row>> create(Row... rows) {
    return Create.of(Arrays.asList(rows)).withRowSchema(ROW_SCHEMA);
  }

  /** Test rows are in the form Row(string f_str='record 156', int f_int=156). */
  public static class ToKV extends DoFn<Row, KV<String, Integer>> {
    @ProcessElement
    public void processElement(ProcessContext c) {
      Row row = c.element();
      c.output(KV.of(row.getValue(0), row.getValue(1)));
    }
  }
}
