Skip to content

Commit 31d7dc2

Browse files
SNOW-988972 adding an example demonstrating how to insert data into VARIANT and OBJECT datatype columns with bind variables (snowflakedb#999)
* SNOW-988972 adding an example demonstrating how to insert data into VARIANT and OBJECT datatype columns with bind variables * SNOW-988972 changes after first review * SNOW-988972 changes * minor reword of printing Create table * adding unique table name * printing query result type * adding DROP after last query * SNOW-988972 changes * renaming directory to cmd/variant from cmd/insertvariantobject * adding defer around the DROP TABLE statement * SNOW-988972 changes * using db.Conn + context to execute all queries in a single connection instead of connecting separately for each of them
1 parent a4c3557 commit 31d7dc2

File tree

2 files changed

+133
-0
lines changed

2 files changed

+133
-0
lines changed

cmd/variant/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
include ../../gosnowflake.mak
2+
CMD_TARGET=variant
3+
4+
## Install
5+
install: cinstall
6+
7+
## Run
8+
run: crun
9+
10+
## Lint
11+
lint: clint
12+
13+
## Format source codes
14+
fmt: cfmt
15+
16+
.PHONY: install run lint fmt

cmd/variant/insertvariantobject.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"encoding/json"
7+
"flag"
8+
"fmt"
9+
"log"
10+
"strconv"
11+
"time"
12+
13+
sf "github.com/snowflakedb/gosnowflake"
14+
)
15+
16+
func main() {
17+
if !flag.Parsed() {
18+
flag.Parse()
19+
}
20+
21+
cfg, err := sf.GetConfigFromEnv([]*sf.ConfigParam{
22+
{Name: "Account", EnvName: "SNOWFLAKE_TEST_ACCOUNT", FailOnMissing: true},
23+
{Name: "User", EnvName: "SNOWFLAKE_TEST_USER", FailOnMissing: true},
24+
{Name: "Password", EnvName: "SNOWFLAKE_TEST_PASSWORD", FailOnMissing: true},
25+
{Name: "Warehouse", EnvName: "SNOWFLAKE_TEST_WAREHOUSE", FailOnMissing: true},
26+
{Name: "Database", EnvName: "SNOWFLAKE_TEST_DATABASE", FailOnMissing: true},
27+
{Name: "Schema", EnvName: "SNOWFLAKE_TEST_SCHEMA", FailOnMissing: true},
28+
{Name: "Host", EnvName: "SNOWFLAKE_TEST_HOST", FailOnMissing: false},
29+
{Name: "Port", EnvName: "SNOWFLAKE_TEST_PORT", FailOnMissing: false},
30+
{Name: "Protocol", EnvName: "SNOWFLAKE_TEST_PROTOCOL", FailOnMissing: false},
31+
})
32+
if err != nil {
33+
log.Fatalf("failed to create Config, err: %v", err)
34+
}
35+
dsn, err := sf.DSN(cfg)
36+
if err != nil {
37+
log.Fatalf("failed to create DSN from Config: %v, err: %v", cfg, err)
38+
}
39+
40+
db, err := sql.Open("snowflake", dsn)
41+
if err != nil {
42+
log.Fatalf("failed to connect. %v, err: %v", dsn, err)
43+
}
44+
defer db.Close()
45+
46+
ctx := context.Background()
47+
conn, err := db.Conn(ctx)
48+
if err != nil {
49+
log.Fatalf("Failed to acquire connection. err: %v", err)
50+
}
51+
defer conn.Close()
52+
53+
tablename := "insert_variant_object_" + strconv.FormatInt(time.Now().UnixNano(), 10)
54+
param := map[string]string{"key": "value"}
55+
jsonStr, err := json.Marshal(param)
56+
if err != nil {
57+
log.Fatalf("failed to marshal json. err: %v", err)
58+
}
59+
60+
createTableQuery := "CREATE TABLE " + tablename + " (c1 VARIANT, c2 OBJECT)"
61+
62+
// https://docs.snowflake.com/en/sql-reference/functions/parse_json
63+
// can do with TO_VARIANT(PARSE_JSON(..)) as well, but PARSE_JSON already produces VARIANT
64+
insertQuery := "INSERT INTO " + tablename + " (c1, c2) SELECT PARSE_JSON(?), TO_OBJECT(PARSE_JSON(?))"
65+
// https://docs.snowflake.com/en/sql-reference/data-types-semistructured#object
66+
insertOnlyObject := "INSERT INTO " + tablename + " (c2) SELECT OBJECT_CONSTRUCT('name', 'Jones'::VARIANT, 'age', 42::VARIANT)"
67+
68+
selectQuery := "SELECT c1, c2 FROM " + tablename
69+
70+
dropQuery := "DROP TABLE " + tablename
71+
72+
fmt.Printf("Creating table: %v\n", createTableQuery)
73+
_, err = conn.ExecContext(ctx, createTableQuery)
74+
if err != nil {
75+
log.Fatalf("failed to run the query. %v, err: %v", createTableQuery, err)
76+
}
77+
defer func() {
78+
fmt.Printf("Dropping the table: %v\n", dropQuery)
79+
_, err = conn.ExecContext(ctx, dropQuery)
80+
if err != nil {
81+
log.Fatalf("failed to run the query. %v, err: %v", dropQuery, err)
82+
}
83+
}()
84+
fmt.Printf("Inserting VARIANT and OBJECT data into table: %v\n", insertQuery)
85+
_, err = conn.ExecContext(ctx, insertQuery,
86+
string(jsonStr),
87+
string(jsonStr),
88+
)
89+
if err != nil {
90+
log.Fatalf("failed to run the query. %v, err: %v", insertQuery, err)
91+
}
92+
fmt.Printf("Now for another approach: %v\n", insertOnlyObject)
93+
_, err = conn.ExecContext(ctx, insertOnlyObject)
94+
if err != nil {
95+
log.Fatalf("failed to run the query. %v, err: %v", insertOnlyObject, err)
96+
}
97+
98+
fmt.Printf("Querying the table into which we just inserted the data: %v\n", selectQuery)
99+
rows, err := conn.QueryContext(ctx, selectQuery)
100+
if err != nil {
101+
log.Fatalf("failed to run the query. %v, err: %v", selectQuery, err)
102+
}
103+
defer rows.Close()
104+
var c1, c2 any
105+
for rows.Next() {
106+
err := rows.Scan(&c1, &c2)
107+
if err != nil {
108+
log.Fatalf("failed to get result. err: %v", err)
109+
}
110+
fmt.Printf("%v (type: %T), %v (type: %T)\n", c1, c1, c2, c2)
111+
}
112+
if rows.Err() != nil {
113+
fmt.Printf("ERROR: %v\n", rows.Err())
114+
return
115+
}
116+
117+
}

0 commit comments

Comments
 (0)