Go言語でテキストファイルの内容をpsqlDBにインポートしたい
解決したいこと
コードをどのように修正すれば解決できるのか教えていただきたいです。
下記のコードでテキストファイルの内容を条件分岐によってDBにコミットしたいのですが、うまくいきません。
テキストファイルの内容から必要なものは変数に代入、足りないものは別に用意してSQLを作成するようにしています。
急に野に放たれプログラムを作成してとのことで、chatGPTを活用しながらここまで来たのですがこの先に進めず困っています。
必要な情報もこれで良いのかも分かりませんが、どうかよろしくお願いいたします。
テキストファイルの内容
0000000000001,20230317,0,仮名 太郎,,19000101,2,長野県飯田市北方9999-1,,,0123456789
0000000000003,20221231,0,仮名 次郎,,19000101,1,長野県飯田市北方9999-2,,,1234567890
0000000000004,20230307,0,仮名 花子,,19000101,1,長野県飯田市北方123-3,,,2345678901
0000000000006,20230311,0,仮名 良子,,19000101,2,長野県飯田市鼎切石1234-4,,,3456789012
DB情報
user_cd character varying(8) Yes
connect_kbn integer
pointcardno character varying
user_nm character varying
user_kn character varying
user_pw character varying
user_mail character varying
birthday date
gender character varying(2)
add1 character varying
add2 character varying
userphone integer
imported character varying(1)
points integer
発生している問題・エラー
SQLが実行されているか分からない。
DBへのコミットが実行されない
該当するソースコード
package main
import (
"bufio"
"database/sql"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strconv"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/transform"
)
func convertShiftJISToUTF8(file string) error {
// shiftjisファイルを開く
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()
// ShiftJISからUTF-8に変換するReaderを作成
utf8Reader := transform.NewReader(f, japanese.ShiftJIS.NewDecoder())
// 変換したデータを読み込む
data, err := ioutil.ReadAll(utf8Reader)
if err != nil {
return err
}
// 変換したデータを元のファイルに上書きする
err = ioutil.WriteFile(file, data, os.ModePerm)
if err != nil {
return err
}
return nil
}
func main() {
//dirフラグを定義する
//dir := flag.String("dir", "C:\\xampp\\htdocs\\point_receive\\00000072", "target directory") //ターゲットのディレクトリ
dir := flag.String("dir", "C:\\xampp\\htdocs\\point_receive\\00000072", "target directory") //ターゲットのディレクトリ
// コマンドライン引数を解析する
flag.Parse()
//最終更新日を持つファイルを走査
var latestModtime time.Time
var latestFile string
err := filepath.Walk(*dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.Mode().IsRegular() && info.ModTime().After(latestModtime) {
latestModtime = info.ModTime()
latestFile = path
}
return nil
})
if err != nil {
fmt.Println("Error", err)
return
}
fmt.Println("Latest modified file", latestFile)
fmt.Println("Latest modification time", latestModtime)
// PostgreSQLデータベースに接続する
db, err := sql.Open("postgres", "postgres://postgres:masterkey@localhost:5432/loglog?sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
//トランザクションを開始
tx, err := db.Begin()
if err != nil {
log.Fatal(err)
}
fmt.Println("success!")
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p)
} else if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}()
// defer func() {
// if err != nil {
// fmt.Println(err)
// tx.Rollback()
// } else {
// err = tx.Commit()
// if err != nil {
// fmt.Println(err)
// }
// }
// }()
// recordExistsは、指定されたユーザーコードがテーブルに存在するかどうかを確認するヘルパー関数
// recordExists := func(pointcardno string) bool {
// var exists bool
// err := tx.QueryRow("SELECT EXISTS(SELECT 1 FROM importusers WHERE pointcardno=$1)", pointcardno).Scan(&exists)
// logError(err, "Failed to check if record exists")
// return exists
// }
recordExists := func(pointcardno string) bool {
var exists bool
err := tx.QueryRow("SELECT EXISTS(SELECT 1 FROM importusers WHERE pointcardno=$1)", pointcardno).Scan(&exists)
logError(err, "Failed to check if record exists")
return exists
}
// latestFileのShiftJISをUTF-8に変換する
err = convertShiftJISToUTF8(latestFile)
if err != nil {
fmt.Println(err)
return
}
// ファイルを開く
file, err := os.Open(latestFile)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
//スキャナを作成
scanner := bufio.NewScanner(file)
//行ごとにデータを読み込む
for scanner.Scan() {
fmt.Println(scanner.Text()) //確認用としてターミナルにスキャンしたファイル名を出力
line := scanner.Text()
fields := strings.Split(line, ",")
if len(fields) <= 12 {
continue
}
// SQL をターミナルに出力
fmt.Println("INSERT INTO importusers (user_cd, connect_kbn, pointcardno, user_nm, user_kn, user_pw, user_mail, birthday, gender, add1, add2, userphone, imported) VALUES (" + fields[0] + ", ',', '" + fields[2] + "', '" + fields[3] + "', '" + fields[4] + "', '', '', '" + fields[6] + "', '', '', '', '', '') ON CONFLICT (user_cd, pointcardno) DO UPDATE SET point = importusers.point + excluded.point, last_date = excluded.last_date;")
//下記変数がテキストファイルの内容を代入する変数
user_cd, _ := strconv.Atoi(fields[0])
last_date := fields[1]
point := fields[2]
user_nm := fields[3]
_ = user_nm
user_kn := fields[4]
_ = user_kn
birthday := fields[5]
_ = birthday
gender := fields[6]
_ = gender
add1 := fields[7]
_ = add1
add2 := fields[8]
_ = add2
add3 := fields[9]
_ = add3
userphone := fields[10]
_ = userphone
imported := "1"
// 変数が空白なら初期値を代入
if last_date == "" {
last_date = "2000/01/01"
}
if point == "" {
point = "0"
}
if user_nm == "" {
user_nm = "''" //ユーザー名が空白の場合は、空文字列を設定する
}
if user_kn == "" {
user_kn = "''" //ユーザーかな名が空白の場合は、空文字列を設定する
}
if birthday == "" {
birthday = "''" //生年月日が空白の場合は、空文字列を設定する
}
if gender == "" {
gender = "''" //性別が空白の場合は、空文字列を設定する
}
if add1 == "" {
add1 = "''" //住所1が空白の場合は、空文字列を設定する
}
if add2 == "" {
add2 = "''" //住所2が空白の場合は、空文字列を設定する
}
if add3 == "" {
add3 = "''" //住所3が空白の場合は、空文字列を設定する
}
if userphone == "" {
userphone = "''" //電話番号が空白の場合は、空文字列を設定する
}
//pointcardnoを作成
pointcardno := "1234567890123"
num := pointcardno
pointcardno = addCheckDigit(num) //チェックディジットを付与した結果を取得
// SQLを作成
if recordExists(pointcardno) {
sql := "UPDATE importusers SET point=$1 WHERE user_cd=$2 AND pointcardno=$3 "
// ステートメントを作成
stmt, err := tx.Prepare(sql)
if err != nil {
logError(err, "Failed to prepare statement")
return
}
defer stmt.Close()
// パラメータをバインドしてステートメントを実行
res, err := stmt.Exec(point, user_cd, pointcardno)
if err != nil {
logError(err, "Failed to execute statement")
return
}
fmt.Println(res)
} else {
sql := "INSERT INTO importusers(user_cd,connect_kbn,pointcardno,user_nm,user_kn,user_pw,user_mail,birthday,gender,add1, add2, userphone, imported, points) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) ON CONFLICT (pointcardno) DO UPDATE SET point = importusers.points + excluded.points;"
// ステートメントを作成
stmt, err := tx.Prepare(sql)
if err != nil {
logError(err, "Failed to prepare statement")
return
}
defer stmt.Close()
// パラメータをバインドしてステートメントを実行
res, err := stmt.Exec("", "0", pointcardno, user_nm, user_kn, "", "", birthday, gender, add1, add2, userphone, imported, point)
logError(err, "Failed to execute statement")
fmt.Println(res)
if err != nil {
logError(err, "Failed to execute statement")
return
}
fmt.Println(res)
}
// // SQL文をターミナルに出力
// query := fmt.Printf("User code: %d, connected: %s, point card no: %s, user name: %s, user kana name: %s, email: %s, birthday: %s, gender: %s, address 1: %s, address 2: %s, phone number: %s\n",fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9], fields[10])
// fmt.Println(query)
query := fmt.Sprintf("INSERT INTO importusers (user_cd, connect_kbn, pointcardno, user_nm, user_kn, user_pw, user_mail, birthday, gender, add1, add2, userphone, imported, points) "+
"VALUES (%s, '','', '%s', '%s', '%s', '', '', '%s', '', '', '', '', ) "+
"ON CONFLICT (user_cd, pointcardno) DO UPDATE SET point = importusers.point + excluded.point, last_date = excluded.last_date",
fields[0], fields[2], fields[3], fields[4], fields[6])
_, err = tx.Exec(query)
// SQL文を実行
stmt, err := tx.Prepare(query)
if err != nil {
logError(err, "Failed to prepare query")
return
}
defer stmt.Close()
_, err = stmt.Exec()
if err != nil {
logError(err, "Failed to execute query")
return
}
}
//トランザクションをコミット
err = tx.Commit()
if err != nil {
fmt.Println(err)
tx.Rollback()
return
}
err = nil
}
自分で試したこと
基本的にchatGPTに質問を投げながら作成しているので、なにをやっているのかも部分部分しか分かっていません。
DBへのアクセスとテキストファイルをコード変換はうまくいっているようです。
情報少なくてすみません。