Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to perform query on AWS athena using Golang SDK

I am new to AWS and Golang, and I am trying to create a lambda function, which will trigger AWS Athena query and email the result using AWS SES service. Even after searching for an hour, I couldn't find a working example of lambda function (in Golang) to perform a query on Athena and getting the output of the query.

While searching, I found code for the same in Java, Python and Node Js, but not in Golang.

Even the Go-SDK page redirects to Java example. But unfortunately, I don't even understand Java.

I have also looked into this AWS SDK for Go API Reference page. But I don't understand what is the flow of the program and which operation to select.

I have tried to create the program for this, this may be completely wrong, and I don't know what to do next. Below is the code -

package main

import (
    "fmt"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/athena"
)

func main() {

    // Create a new session in the us-west-2 region.
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("us-east-1")},
    )

    // Create an Athena session.
    client := athena.New(sess)

    // Example sending a request using the StartQueryExecutionRequest method.
    query := "SELECT * FROM table1 ;"
    params := query
    req, resp := client.StartQueryExecutionRequest(params)

    err1 := req.Send()
    if err1 == nil { // resp is now filled
        fmt.Println(resp)
    }
}

Appreciate if someone can help me to perform an Athena query and to get its result in Golang(Preferably) or can share some resource. Once I get it, I can then send an email using AWS SES.

like image 362
Rahul Satal Avatar asked Sep 19 '25 05:09

Rahul Satal


2 Answers

Use this to get started.

// run as: go run main.go
package main

import (
    "context"
    "fmt"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/endpoints"
    "github.com/aws/aws-sdk-go-v2/aws/external"
    "github.com/aws/aws-sdk-go-v2/service/athena"
)

const table = "textqldb.textqltable"
const outputBucket = "s3://bucket-name-here/"

func main() {

    cfg, err := external.LoadDefaultAWSConfig()
    if err != nil {
        fmt.Printf("config error: %v\n", err)
        return
    }

    cfg.Region = endpoints.UsEast2RegionID

    client := athena.New(cfg)

    query := "select * from " + table

    resultConf := &athena.ResultConfiguration{
        OutputLocation: aws.String(outputBucket),
    }

    params := &athena.StartQueryExecutionInput{
        QueryString:         aws.String(query),
        ResultConfiguration: resultConf,
    }

    req := client.StartQueryExecutionRequest(params)

    resp, err := req.Send(context.TODO())
    if err != nil {
        fmt.Printf("query error: %v\n", err)
        return
    }

    fmt.Println(resp)
}
like image 164
Everton Avatar answered Sep 20 '25 22:09

Everton


@Everton's code is executing a query on Athena, and its responses are getting saved on S3 bucket and not getting returned. So, I have added the code to execute the Athena query and get the response back. Hope this may help others.

// run as: go run main.go
package main

import (
    "context"
    "fmt"
    "time"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/aws/endpoints"
    "github.com/aws/aws-sdk-go-v2/aws/external"
    "github.com/aws/aws-sdk-go-v2/service/athena"
)

const table = "<Database_Name>.<Table_Name>"
const outputBucket = "s3://bucket-name-here/"

// Execute the query and return the query ID
func executeQuery(query string) *string {

    cfg, err := external.LoadDefaultAWSConfig()
    if err != nil {
        fmt.Printf("config error: %v\n", err)
    }

    cfg.Region = endpoints.UsEast2RegionID

    client := athena.New(cfg)

    resultConf := &athena.ResultConfiguration{
        OutputLocation: aws.String(outputBucket),
    }

    params := &athena.StartQueryExecutionInput{
        QueryString:         aws.String(query),
        ResultConfiguration: resultConf,
    }

    req := client.StartQueryExecutionRequest(params)

    resp, err := req.Send(context.TODO())
    fmt.Println("Response is: ", resp, " Error is:", err)

    if err != nil {
        fmt.Printf("Query Error: %v\n", err)
    }

    fmt.Println("Query Execution Response ID:", resp.QueryExecutionId)
    return resp.QueryExecutionId
}

// Takes queryId as input and returns its response
func getQueryResults(QueryID *string) (*athena.GetQueryResultsResponse, error) {

    cfg, err := external.LoadDefaultAWSConfig()
    if err != nil {
        panic("config error")
    }

    cfg.Region = endpoints.UsEast2RegionID
    client := athena.New(cfg)
    params1 := &athena.GetQueryResultsInput{
        QueryExecutionId: QueryID,
    }
    req := client.GetQueryResultsRequest(params1)

    resp, err := req.Send(context.TODO())

    if err != nil {
        fmt.Printf("Query Response Error: %v\n", err)
        return nil, err
    }
    return resp, nil

}

func main() {

    query := "select * from " + table

    // Execute an Athena Query
    QueryID := executeQuery(query)


    // Get the response of the query

    // Wait for some time for query completion
    time.Sleep(15 * time.Second) // Otherwise create a loop and try for every x seconds
    Resp, err := getQueryResults(QueryID)

    if err != nil {
        fmt.Printf("Error getting Query Response: %v\n", err)
    } else {
        fmt.Println(" \nRows:", Resp.ResultSet.Rows)
    }

}
like image 32
Rahul Satal Avatar answered Sep 20 '25 20:09

Rahul Satal