2020/05,江端さんの技術メモ

pgRoutingをはじめて使ってみた」を、そのまま試させて頂いた

C:\Users\ebata>docker start -a ebata_db_1 ← pgRoutingで作ったDockerのDB
C:\Users\ebata>docker container exec -it ebata_db_1 bash ← ログインできる
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
routing | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
postgres=# CREATE DATABASE d1; ← d1というログインできる
CREATE DATABASE
postgres=# \c d1 ← d1に接続
You are now connected to database "d1" as user "postgres".
d1=# CREATE EXTENSION postgis;
CREATE EXTENSION
d1=# CREATE EXTENSION pgrouting;
CREATE EXTENSION
d1=# CREATE TABLE edges (id serial, source int, target int, cost int); ← テーブルを作成する
CREATE TABLE
d1=# INSERT INTO edges (source, target, cost) VALUES (1, 2, 7), (1, 3, 9), (1, 6, 14), (2, 3, 10), (2, 4, 15), (3, 4, 11), (3, 6, 2), (4, 5, 6), (5, 6, 9); ← 端点ノード1、端点ノード2、コスト
INSERT 0 9
d1=# SELECT seq, node, edge, cost FROM pgr_dijkstra('SELECT id, source, target, cost FROM edges', 1, 5, directed:=false); ← ノード1からノード5までの最短コストを算出する
seq | node | edge | cost
-----+------+------+------
1 | 1 | 2 | 9
2 | 3 | 7 | 2
3 | 6 | 9 | 9
4 | 5 | -1 | 0
(4 rows)
1->3->6->5の最短コストが出てくる。

2020/05,江端さんの技術メモ

C:\Users\ebata>docker pull postgres:12.2
12.2: Pulling from library/postgres
bc51dd8edc1b: Pull complete
d2b355dbb6c6: Pull complete
d237363a1a91: Pull complete
ff4b9d2fde66: Pull complete
646492d166e7: Pull complete
828b1f103a3a: Pull complete
2ab9e3c9583f: Pull complete
4ab234e8a047: Pull complete
71b084e0c62f: Pull complete
bf30bd092a82: Pull complete
2aa61e9feb4e: Pull complete
aa5eca126d57: Pull complete
7046b64d69a3: Pull complete
a851dbb990ce: Pull complete
Digest: sha256:c5423e0febf82c33b5dc69aacd70d64418144db7bd355fa4ca30e6e5430b4123
Status: Downloaded newer image for postgres:12.2
docker.io/library/postgres:12.2

C:\Users\ebata>docker run -d --name postgres122 -e POSTGRES_PASSWORD=test -p 5432:5432 postgres:12.2
839317f0bb705daf5eac55cc6b4f74e0cbc49ff2f64e1efc9dd5e4d3f03e6515

C:\Users\ebata>docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
839317f0bb70 postgres:12.2 "docker-entrypoint.s…" 17 seconds ago Up 14 seconds 0.0.0.0:5432->5432/tcp postgres122

C:\Users\ebata>docker exec -ti postgres122 bash

2.準備
Windows10 BOX のC:\直下に、routing-20200221.sql を置いておく

3.ファイルのコピー
C:\Users\ebata>docker cp c:\routing-20200221.sql postgres122:/tmp/
でDockerの内部にコピー

4.コンテナに入る
C:\Users\ebata>docker exec -i -t postgres122 /bin/bash

5.コピーされているかを確認する
root@839317f0bb70:/# cd tmp
root@839317f0bb70:/tmp# ls
で、
routing-20200221.sql
が表示されたので成功

6.ローカルにdocker-compose.ymlを作成する

version: '3.7'

services:
  db:
    image: pgrouting/pgrouting:v3.0.0-dev-postgresql_12
    expose:
      - 5432
    ports:
    - 15432:5432
    volumes:
      - db_data
      - ./shared:/shared
  db_data:
    image: busybox
    volumes:
      - /data/db

8.次のコマンドを実施する
C:\Users\ebata>docker-compose up -d


9.DBの作成
C:\Users\ebata>docker-compose exec db createdb -h db -U postgres routing


10.postgisのインストール
C:\Users\ebata>docker-compose exec db psql -h db -U postgres -d routing -c 'CREATE EXTENSION pgrouting CASCADE; CREATE EXTENSION hstore;'


11.ダンプしたsqlの取り込み
C:\Users\ebata>docker-compose exec db psql -h db -U postgres routing -f /shared/routing-20200221.sql

2020/05,江端さんの技術メモ

can’t find package “github.com/lib/pq”

と、

Dockerで作ったpostgreSQLへの外部クライアントからのアクセス方法

を実施して、GoのプログラムからPostgreSQLサーバ(Docker版)にアクセスすることができました。

/*
go build -gcflags "-N -l" main.go

uft-8でセーブ

まず、以下の手順でテーブルを作っておく
 
C:\Users\yrl-user>psql -h localhost -U postgres	

postgres=# create database blogapp;

postgres=# \l		
postgres=# \connect blogapp(データベース名)
 
以下をコピペしてテーブルとその内容を直接書き込む
 
create table users (
	   id serial primary key,
	   name varchar(255),
	   score real,
	   team varchar(255)
					);
 
insert into users (name, score, team) values
('taguchi', 5.5, 'red'),
('fkoji', 8.3, 'blue'),
('dotinstall', 2.2, 'blue'),
('sakaki', 5.0, 'green'),
('sasaki', 4.6, 'red'),
('kimura', 4.7, 'green');
 
blogapp=# \dt
blogapp=# \d users(テーブル名)
 
データベースのテーブルの中身を確認する
blogapp=# select * from users; // 検索の基本形
 
*/



package main

import (
    "fmt"
    "database/sql"
    _ "github.com/lib/pq"
    "os"
)

// ----------------------------------------------------------------

func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "fatal: error: %s", err.Error())
		os.Exit(1)
	}
}

func main() {
    fmt.Fprintln (os.Stderr,"*** start ***")

	db, err := sql.Open("postgres", "user=postgres dbname=blogapp password=c-anemone sslmode=disable")

	checkError(err)
    defer db.Close()

	sql_str := "select id,name,score,team from users order by id"

    rows, err := db.Query(sql_str)
    if err != nil {
        fmt.Println(err)
        }

    defer rows.Close()

    for rows.Next() {
        var id string
        var name string 
        var score float32
        var team string 
        if err := rows.Scan(&id,&name,&score,&team); err != nil {
            fmt.Println(err)
        }
        fmt.Printf ("%s\t%s\t%f\t%s\n",id, name,score,team)
    }

    if err := rows.Err(); err != nil {
        fmt.Println(err)
        }

    fmt.Fprintln (os.Stderr,"*** end ***")
}

出力結果

*** start ***
1	taguchi	5.500000	red
2	fkoji	8.300000	blue
3	dotinstall	2.200000	blue
4	sakaki	5.000000	green
5	sasaki	4.600000	red
6	kimura	4.700000	green
*** end ***

ようやく一安心できました。

2020/05,江端さんの技術メモ

「DockerのpostgreSQLの起動方法」で、postgreSQL(ポスグレ)サーバは作れたのは良かったのですが、クライアント(例 pgAdmin4)からアクセスできないことが分かりました。どうやら原因は、パスワードがない、ということのようです。fe_sendauth: no password suppliedが消えません。

私は、CとかGoのプログラムから、ポスグレを使おうとしていますが、pgAdmin4からアクセスできないとなると、多分、「CとかGoのプログラムからは動せない」と思いました。

ロールやらなんやらを追加する方法もあるようですが、私は、ポスグレの運用は、できるだけ手を抜きたいし、そもそもポスグレを外部公開する予定はないので、セキュリティもスカスカでかまいません(もちろん、SSHなんぞも不要)。

そこで、Dockerのポスグレにパスワード("c-anemone")を追加しました。

C:\Users\ebata>docker start -a postgres122

C:\Users\ebata>docker container exec -it postgres122 bash

root@19e323b3f7c1:/# psql -U postgres

とした状態で、

postgres=# alter role postgres with password 'c-anemone';

と打ち込んだ後、psqlからログアウトして、別のコンソールから、

C:\Users\ebata>docker stop postgres122

C:\Users\ebata>docker start -a postgres122

と再起動をしました。

その後、pgAdmin4のCreateの設定画面にパスワードを入力したら、

さくっとログインできました。

2020/05,江端さんの技術メモ

よく忘れるのでメモしておく。

C:\Users\ebata>docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19e323b3f7c1 postgres:12.2 "docker-entrypoint.s…" 2 months ago Exited (255) 2 months ago 0.0.0.0:5432->5432/tcp postgres122
70fa5aa3a11d pgrouting/pgrouting:v3.0.0-dev-postgresql_12 "docker-entrypoint.s…" 2 months ago Exited (255) 2 months ago 0.0.0.0:15432->5432/tcp ebata_db_1
78c979ee1238 busybox "sh" 2 months ago Exited (0) 2 months ago ebata_db_data_1
C:\Users\ebata>docker start -a postgres122
PostgreSQL Database directory appears to contain a database; Skipping initialization
2020-05-24 15:58:13.237 UTC [1] LOG: starting PostgreSQL 12.2 (Debian 12.2-2.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
2020-05-24 15:58:13.250 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2020-05-24 15:58:13.250 UTC [1] LOG: listening on IPv6 address "::", port 5432
2020-05-24 15:58:13.290 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2020-05-24 15:58:13.352 UTC [24] LOG: database system was interrupted; last known up at 2020-03-12 10:28:44 UTC
2020-05-24 15:58:13.535 UTC [24] LOG: database system was not properly shut down; automatic recovery in progress
2020-05-24 15:58:13.568 UTC [24] LOG: redo starts at 0/166F4D8
2020-05-24 15:58:13.569 UTC [24] LOG: invalid record length at 0/166F5C0: wanted 24, got 0
2020-05-24 15:58:13.569 UTC [24] LOG: redo done at 0/166F588
2020-05-24 15:58:13.730 UTC [1] LOG: database system is ready to accept connections
C:\Users\ebata>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
19e323b3f7c1 postgres:12.2 "docker-entrypoint.s…" 2 months ago Up 13 minutes 0.0.0.0:5432->5432/tcp postgres122
C:\Users\ebata>docker container exec -it postgres122 bash
root@19e323b3f7c1:/# ls
bin boot dev docker-entrypoint-initdb.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@19e323b3f7c1:/# psql -U postgres
psql (12.2 (Debian 12.2-2.pgdg100+1))
Type "help" for help.
postgres-# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
ca_db | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
postgres-# \c ca_db
You are now connected to database "ca_db" as user "postgres".

その他、viを使いたければ、

root@19e323b3f7c1:/#apt-get update

root@19e323b3f7c1:/#apt-get install vim

2020/05,江端さんの技術メモ

下記のプログラムをコンパイルする

/*
		go build -gcflags "-N -l" main.go
*/
package main

import (
    "fmt"
    "database/sql"
    _ "github.com/lib/pq"
    "os"
)

// ----------------------------------------------------------------
func main() {
    fmt.Fprintln (os.Stderr,"*** 開始 ***")
    db, err := sql.Open("postgres", "user=scott dbname=city password=tiger123 sslmode=disable")
    defer db.Close()

    sql_str := "select id,name,population,date_mod from cities order by id"

    rows, err := db.Query(sql_str)
    if err != nil {
        fmt.Println(err)
        }
    defer rows.Close()

    for rows.Next() {
        var id string
        var name string 
        var population int
        var date_mod string 
        if err := rows.Scan(&id,&name,&population,&date_mod); err != nil {
            fmt.Println(err)
        }
        fmt.Printf ("%s\t%s\t%d\t%s\n",id, name,population,date_mod)
    }

    if err := rows.Err(); err != nil {
        fmt.Println(err)
        }

    fmt.Fprintln (os.Stderr,"*** 終了 ***")
}

で "github.com/lib/pq" がない、とエラーが出てくる。

C:\Users\ebata>go get github.com/lib/pq

で、すんなりインストール成功。で、コンパイルをしたら通ったので、とりあえずメモしておく。これからdockerでDBつくって動作を試す。

2020/05,江端さんの技術メモ

package main

import (
	"fmt"
	"strings"
)

func main() {
	c0 := make(chan string)  // makeってなんだ? →"配列"でも"共有メモリ"でもいいが、
	c1 := make(chan string)  // 江端理解では「トンネル」とか「パイプ」とか「Amazonのダンボール箱」 

	go sourceGopher(c0)      // "c0"とラベルの付いたダンボール箱を使うぜ
	go filterGopher(c0, c1)  // "c0","c1"とラベルの付いたダンボール箱を使うぜ 
	printGopher(c1)          // "c1"とラベルの付いたダンボール箱を使うぜ
}

func sourceGopher(downstream chan string) {
	for _, v := range []string{"hello world", "a bad apple", "goodbye all"} {
		downstream <- v   // "c0"のダンボール箱に、(1)"hello world",(2)"a bad apple", (3)"goodbye all"を投げ入れる
	}
	downstream <- ""   // "c0"のダンボール箱の底にクッション(プチプチ)を入れる
}

func filterGopher(upstream, downstream chan string) {
	for {
		item := <-upstream     // "c0"のダンボール箱からクッションを取り出す
		if item == "" {        // クッションだったら
			downstream <- ""   // "c1"のダンボール箱にクッションを入れる
			return             // ダンボール箱の蓋を閉める
		}
		if !strings.Contains(item, "bad") {   // "bad"という文字列が入っていない荷物だったら
			downstream <- item // "c1"のダンボール箱に荷物を入れる
		}
	}
}
func printGopher(upstream chan string) {
	for {
		v := <-upstream // "c1"のダンボール箱から荷物を出す
		if v == "" {    // "c1"の荷物がクッションだったら
			 return     // ダンボール箱を閉める
		}
		fmt.Println(v)  // 荷物を読み上げる
	}
}

2020/05,江端さんの技術メモ

良く忘れるので書いておく。

(1)Goは一度も使われない変数があると、全部エラーにしてしまう → 「せっかく買ったのに、どうして使わないの?」と言い続ける、うっとうしい母親みたいなもの

(2)返り値のある変数があるけど、別に返り値が必要でないときがある。
例えば、2つの返り値がある関数で、「2つもはいらんわ」という時に、こうなる

f := func(num1 int, num2 int)(int, int){
	return num1 + num2, num1 - num2
}
ret1, ret2 := f(8, 7)  // "a"が不使用のためエラー:a declared and not used
fmt.Println(ret2)

(3)でも、こうすれば、エラーにならない

ret1 はいらん → これを"_"と書く

_, ret2 := f(8, 7)  // エラーがでてこなくなる
fmt.Println(ret2)

2020/05,江端さんの技術メモ

// go build -gcflags "-N -l" main.go ← これで、golangのプログラムをgdbで動かすことができたぞ(マグレかもしれないけど)

package main

import (
    "fmt"
    "time"
)

func counting(c chan<- int) {
    for i := 0; i < 10; i++ {
        time.Sleep(2 * time.Second)
        c <- i
    }
    close(c)
}

func main() {
    msg := "Starting main"
    fmt.Println(msg)
    bus := make(chan int)
    msg = "starting a gofunc"
    go counting(bus)

    for count := range bus {
        fmt.Println("count:", count)
    }
}