Posted at

Go言語でRedshiftとつなぐ(というかただのPostgreSQL)

More than 3 years have passed since last update.


ゴール


  • Go言語からRedshiftにつないでクエリとかする


Redshiftとは

Redshiftへの接続およびクエリはPostgresだと思ってだいたい問題ないっぽいです。(一度、ISNULL使っててRedshiftにはISNULL無いのでCOALESCE使う、みたいなつまずきがありましたが...)


Go言語からPostgresにつなぐ

どこにでもあるGoでsql使うサンプルです

package main

import (
"database/sql"
"log"

_ "github.com/lib/pq"
)

// User 適当に
type User struct {
Name string `sql:"username"`
}

func main() {
db, err := sql.Open("postgres", "postgres://user:pass@host:port/dbname")
if err != nil {
log.Fatalln("つなぐの", err)
}
defer db.Close()

row, err := db.Query("SELECT username FROM users WHERE username LIKE $1 LIMIT $2", "otiai%", 10)
if err != nil {
log.Fatalln("クエリするの", err)
}

for row.Next() { // 行があるまでtrue
user := new(User)
err := row.Scan(&user.Name)
if err != nil {
log.Fatalln("結果をスキャンするの", err)
}

log.Printf("%+v\n", user)
}
if err := row.Err(); err != nil {
log.Fatalln("イテレーション中の", err)
}
}

上記の、postgres://user:pass@host:port/dbnameに該当するところを、お使いの(RDSなり)Redshiftのインスタンスであるところのfoo.bar.region.redshift.amazonaws.com:5439とかにすれば、普通に動くはずです。


めんどいのでORMつかおう

もはやRedshift関係無いんですが、Goのdatabase/sql十分可愛いけど、row.Nextとかrow.Scanとかめんどいので、そのへんもいい感じにマッピングしてくれるやつ使う。

今回はgormで

 package main

import (
- "database/sql"
"log"

+ "github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)

// User 適当に
type User struct {
- Name string `sql:"username"`
+ Name string `gorm:"column:username"`
}

func main() {
- db, err := sql.Open("postgres", "postgres://user:pass@host:port/dbname")
+ db, err := gorm.Open("postgres", "postgres://user:pass@host:port/dbname")
if err != nil {
log.Fatalln("つなぐの", err)
}
defer db.Close()

- row, err := db.Query("SELECT username FROM users WHERE username LIKE $1", "otiai%")
+ users := []User{}
+ err = db.Where("username LIKE ?", "otiai%").Limit(10).Find(&users).Error
if err != nil {
- log.Fatalln("クエリするの", err)
- }
-
- for row.Next() { // 行があるまでtrue
- user := new(User)
- err := row.Scan(&user.Name)
- if err != nil {
- log.Fatalln("結果をスキャンするの", err)
- }
-
- log.Printf("%+v\n", user)
- }
- if err := row.Err(); err != nil {
- log.Fatalln("イテレーション中の", err)
+ log.Fatalln("クエリしてスキャンするの", err)
}
+ log.Printf("%+v\n", users)
}

すげー楽。gormが、Findとかで渡すstructのtype名見て、この場合勝手にusersというテーブル名を入れます。発行されるSQLを生で見たい場合は

db.LogMode(true)

と、どっかにはさめばstdoutに出ます。


というか

ぜんぜんRedshiftの記事じゃなかった...