#
# 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 for SqlTransform and related classes."""

# pytype: skip-file

import typing

from apache_beam.transforms.external import BeamJarExpansionService
from apache_beam.transforms.external import ExternalTransform
from apache_beam.transforms.external import NamedTupleBasedPayloadBuilder

__all__ = ['SqlTransform']

SqlTransformSchema = typing.NamedTuple(
    'SqlTransformSchema',
    [('query', str), ('dialect', typing.Optional[str]),
     ('ddl', typing.Optional[str])])


class SqlTransform(ExternalTransform):
  """A transform that can translate a SQL query into PTransforms.

  Input PCollections must have a schema. Currently, there are two ways to define
  a schema for a PCollection:

  1) Register a `typing.NamedTuple` type to use RowCoder, and specify it as the
     output type. For example::

      Purchase = typing.NamedTuple('Purchase',
                                   [('item_name', unicode), ('price', float)])
      coders.registry.register_coder(Purchase, coders.RowCoder)
      with Pipeline() as p:
        purchases = (p | beam.io...
                       | beam.Map(..).with_output_types(Purchase))

  2) Produce `beam.Row` instances. Note this option will fail if Beam is unable
     to infer data types for any of the fields. For example::

      with Pipeline() as p:
        purchases = (p | beam.io...
                       | beam.Map(lambda x: beam.Row(item_name=unicode(..),
                                                     price=float(..))))

  Similarly, the output of SqlTransform is a PCollection with a schema.
  The columns produced by the query can be accessed as attributes. For example::

    purchases | SqlTransform(\"\"\"
                  SELECT item_name, COUNT(*) AS `count`
                  FROM PCOLLECTION GROUP BY item_name\"\"\")
              | beam.Map(lambda row: "We've sold %d %ss!" % (row.count,
                                                             row.item_name))

  Additional examples can be found in
  `apache_beam.examples.wordcount_xlang_sql`, `apache_beam.examples.sql_taxi`,
  and `apache_beam.transforms.sql_test`.

  For more details about Beam SQL in general, see the `Java transform
  <https://beam.apache.org/releases/javadoc/current/org/apache/beam/sdk/extensions/sql/SqlTransform.html>`_,
  and the `documentation
  <https://beam.apache.org/documentation/dsls/sql/overview/>`_.
  """
  URN = 'beam:external:java:sql:v1'

  def __init__(self, query, dialect=None, ddl=None, expansion_service=None):
    """
    Creates a SqlTransform which will be expanded to Java's SqlTransform.
    (See class docs).
    :param query: The SQL query.
    :param dialect: (optional, deprecated) The dialect.
    :param ddl: (optional) The DDL statement.
    :param expansion_service: (optional) The URL of the expansion service to use
    """
    expansion_service = expansion_service or BeamJarExpansionService(
        ':sdks:java:extensions:sql:expansion-service:shadowJar')
    super().__init__(
        self.URN,
        NamedTupleBasedPayloadBuilder(
            SqlTransformSchema(query=query, dialect=dialect, ddl=ddl)),
        expansion_service=expansion_service)
