github.com/apache/beam/sdks/v2@v2.48.2/go/examples/xlang/sql/sql.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one or more
     2  // contributor license agreements.  See the NOTICE file distributed with
     3  // this work for additional information regarding copyright ownership.
     4  // The ASF licenses this file to You under the Apache License, Version 2.0
     5  // (the "License"); you may not use this file except in compliance with
     6  // the License.  You may obtain a copy of the License at
     7  //
     8  //    http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  // The sql example demonstrates how to run a cross-language SQL transform
    17  // in a Beam Go Pipeline.
    18  
    19  // Prerequisites to run sql:
    20  // –> [Required] Job needs to be submitted to a portable runner (--runner=universal)
    21  // –> [Required] Endpoint of job service needs to be passed (--endpoint=<ip:port>)
    22  // –> [Required] Endpoint of expansion service needs to be passed (--expansion_addr=<ip:port>)
    23  // –> [Optional] Environment type can be LOOPBACK. Defaults to DOCKER. (--environment_type=LOOPBACK|DOCKER)
    24  package main
    25  
    26  import (
    27  	"context"
    28  	"flag"
    29  	"fmt"
    30  	"log"
    31  	"reflect"
    32  
    33  	"github.com/apache/beam/sdks/v2/go/pkg/beam"
    34  	"github.com/apache/beam/sdks/v2/go/pkg/beam/testing/passert"
    35  	"github.com/apache/beam/sdks/v2/go/pkg/beam/transforms/sql"
    36  	"github.com/apache/beam/sdks/v2/go/pkg/beam/x/beamx"
    37  )
    38  
    39  var (
    40  	expansionAddr = flag.String("expansion_addr", "", "Address of Expansion Service")
    41  )
    42  
    43  // Move is a struct wrapping information about a character's moves in a video
    44  // game. Each field is exported so the type has a schema inferred for it that
    45  // is passed to the expansion service when the cross-language transform is called.
    46  type Move struct {
    47  	Character string
    48  	MoveName  string
    49  }
    50  
    51  func (m *Move) String() string {
    52  	return fmt.Sprintf("Character: %v, Move %v", m.Character, m.MoveName)
    53  }
    54  
    55  func blankaMoves() []Move {
    56  	var moves []Move
    57  	moves = append(moves, Move{Character: "Blanka", MoveName: "Vertical Rolling"})
    58  	moves = append(moves, Move{Character: "Blanka", MoveName: "Rolling Attack"})
    59  	moves = append(moves, Move{Character: "Blanka", MoveName: "Electric Thunder"})
    60  	return moves
    61  }
    62  
    63  func sagatMoves() []Move {
    64  	var moves []Move
    65  	moves = append(moves, Move{Character: "Sagat", MoveName: "Tiger Shot"})
    66  	moves = append(moves, Move{Character: "Sagat", MoveName: "Tiger Knee Crush"})
    67  	moves = append(moves, Move{Character: "Sagat", MoveName: "Tiget Uppercut"})
    68  	return moves
    69  }
    70  
    71  func ryuMoves() []Move {
    72  	var moves []Move
    73  	moves = append(moves, Move{Character: "Ryu", MoveName: "Hadouken"})
    74  	moves = append(moves, Move{Character: "Ryu", MoveName: "Shoryuken"})
    75  	moves = append(moves, Move{Character: "Ryu", MoveName: "Tatsumaki Senpuukyaku"})
    76  	return moves
    77  }
    78  
    79  func makeDemoMoves() []Move {
    80  	blanka := blankaMoves()
    81  	sagat := sagatMoves()
    82  	ryu := ryuMoves()
    83  	var moves []Move
    84  	moves = append(moves, blanka...)
    85  	moves = append(moves, sagat...)
    86  	moves = append(moves, ryu...)
    87  	return moves
    88  }
    89  
    90  func main() {
    91  	flag.Parse()
    92  	beam.Init()
    93  
    94  	p, s := beam.NewPipelineWithRoot()
    95  
    96  	moves := makeDemoMoves()
    97  	pcol := beam.CreateList(s, moves)
    98  
    99  	// Options for the sql transform have to be defined before the Transform call.
   100  	var opts []sql.Option
   101  	// Dialect options are "calcite" and "zetasql"
   102  	opts = append(opts, sql.Dialect("calcite"))
   103  	// The expansion address can be specified per-call here or overwritten for all
   104  	// calls using xlangx.RegisterOverrideForUrn(sqlx.Urn, *expansionAddr).
   105  	opts = append(opts, sql.ExpansionAddr(*expansionAddr))
   106  	// The PCollection input name currently does not matter, as it will be referred
   107  	// to as "PCOLLECTION" in the query
   108  	opts = append(opts, sql.Input("moves", pcol))
   109  	// Specify the expected output type of the returned PCollection. This is type
   110  	// checked at pipeline construction time, not run time.
   111  	opts = append(opts, sql.OutputType(reflect.TypeOf(Move{})))
   112  
   113  	// The query should be provded as a string in the SQL dialect specified in the options
   114  	// above. When specifying fields from the struct, wrap the names in ``
   115  	query := "SELECT * FROM PCOLLECTION WHERE `Character` = 'Blanka'"
   116  
   117  	if *expansionAddr != "" {
   118  		// The expansion address can be specified per-call here or overwritten for all
   119  		// calls using xlangx.RegisterOverrideForUrn(sqlx.Urn, *expansionAddr).
   120  		opts = append(opts, sql.ExpansionAddr(*expansionAddr))
   121  	} else {
   122  		log.Print("no expansion service address provided, will start automated service")
   123  	}
   124  
   125  	outputCollection := sql.Transform(s, query, opts...)
   126  
   127  	// We aren't saving our output, so we will just check that the query returned the correct
   128  	// output (in this case, only Blanka's move list.)
   129  	passert.EqualsList(s, outputCollection, blankaMoves())
   130  
   131  	if err := beamx.Run(context.Background(), p); err != nil {
   132  		log.Fatalf("Failed to execute job: %v", err)
   133  	}
   134  }