Closed aidanmelen closed 1 year ago
According to the gosnowflakedb docs for Executing Multiple Statements in One Call, we should be using QueryContext
like similar to ExecContext
.
Example code for a multistatement query context and process all of the resulting query rows:
package main
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"log"
"os"
"time"
"github.com/snowflakedb/gosnowflake"
)
func main() {
// Initialize the `statements` variable with multiple Snowflake query statement strings
statements := `
SHOW ROLES LIKE 'SYSADMIN';
SHOW ROLES LIKE 'ACCOUNTADMIN';
`
// Set up a Snowflake connection
cfg := &gosnowflake.Config{
Account: os.Getenv("SNOWFLAKE_ACCOUNT"),
User: os.Getenv("SNOWFLAKE_USER"),
Password: os.Getenv("SNOWFLAKE_PASSWORD"),
Database: os.Getenv("SNOWFLAKE_DATABASE"),
Schema: os.Getenv("SNOWFLAKE_SCHEMA"),
Warehouse: os.Getenv("SNOWFLAKE_WAREHOUSE"),
}
dsn, err := gosnowflake.DSN(cfg)
if err != nil {
log.Fatal(err)
}
db, err := sql.Open("snowflake", dsn)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Set up a context with a timeout
ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
// Query Snowflake using the WithMultiStatement method
multiStmtCtx, err := gosnowflake.WithMultiStatement(ctx, 0)
if err != nil {
log.Fatal(err)
}
rows, err := db.QueryContext(multiStmtCtx, statements)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Process all the rows from all the queries and store the results in a list
results := make([]map[string]interface{}, 0)
processRows := func(rows *sql.Rows) error {
for rows.Next() {
columns, err := rows.Columns()
if err != nil {
return err
}
values := make([]interface{}, len(columns))
for i := range columns {
values[i] = new(interface{})
}
err = rows.Scan(values...)
if err != nil {
return err
}
rowMap := make(map[string]interface{})
for i, col := range columns {
rowMap[col] = *values[i].(*interface{})
}
results = append(results, rowMap)
}
if err := rows.Err(); err != nil {
return err
}
return nil
}
if err := processRows(rows); err != nil {
log.Fatal(err)
}
for rows.NextResultSet() {
if err := processRows(rows); err != nil {
log.Fatal(err)
}
}
marshalledResults, _ := json.Marshal(results)
fmt.Printf("%v", string(marshalledResults))
}
and run with:
$ go run main.go | jq
[
{
"assigned_to_users": "0",
"comment": "System administrator can create and manage databases and warehouses.",
"created_on": "2021-11-02T19:45:29.136-07:00",
"granted_roles": "0",
"granted_to_roles": "1",
"is_current": "N",
"is_default": "N",
"is_inherited": "Y",
"name": "SYSADMIN",
"owner": ""
},
{
"assigned_to_users": "2",
"comment": "Account administrator can manage all aspects of the account.",
"created_on": "2021-11-02T19:45:29.108-07:00",
"granted_roles": "2",
"granted_to_roles": "0",
"is_current": "Y",
"is_default": "Y",
"is_inherited": "N",
"name": "ACCOUNTADMIN",
"owner": ""
}
]
Affected Resource(s)
Please list the resources as a list, for example:
snowsql_exec
If this issue appears to affect multiple resources, it may be an issue with Terraform's core, so please mention this.
Terraform Configuration Files
Expected Behavior
The
read
block should work like the other nested blocks. The following error should be presented to the user when theread.0.statements
does not match theread.0.number_of_statements
in order to protect against sql injection.Actual Behavior
The
read.0.statements
queries are run and theread.0.number_of_statements
is ignored.