package main

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

const (
	pg_char = "bpchar"
)

type pg_pk_info struct {
	name     string
	colname  string
	typename string
}

func findPrimaryKey_pg(cd checkDbInfo, tbl string) (string, error) {
	const pg_find_pk = `SELECT pg_constraint.conname AS pk_name,
    pg_attribute.attname AS colname,
    pg_type.typname AS typename
FROM
    pg_constraint
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid
AND pg_attribute.attnum = pg_constraint.conkey [ 1 ]
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid
WHERE
    pg_class.relname = '%s'
AND pg_constraint.contype = 'p'`
	row := cd.db.QueryRow(fmt.Sprintf(pg_find_pk, tbl))
	var pk pg_pk_info
	err := row.Scan(&pk.name, &pk.colname, &pk.typename)
	return pk.colname, err
}

type pg_col struct {
	OID       int
	AttNum    int
	Field     string
	Type      string
	Length    int
	Lengthvar int
	NotNull   bool
}

func getTableColumnInfo_pg(db *sql.DB, tbl string) (ret []ColumnInfo, err error) {
	const pg_column_info = `SELECT c.oid,a.attnum,a.attname AS field,t.typname AS type,a.attlen AS length,a.atttypmod AS lengthvar,a.attnotnull AS notnull
FROM pg_class c,pg_attribute a,pg_type t
WHERE c.relname = '%s' and a.attnum > 0 and a.attrelid = c.oid and a.atttypid = t.oid
ORDER BY a.attnum;`
	rows, err := db.Query(fmt.Sprintf(pg_column_info, tbl))
	if err != nil {
		return nil, fmt.Errorf("getTableColumnInfo_pg err1ß:%w", err)
	}
	for rows.Next() {
		var r pg_col
		err = rows.Scan(&r.OID, &r.AttNum, &r.Field, &r.Type, &r.Length, &r.Lengthvar, &r.NotNull)
		if err != nil {
			return nil, fmt.Errorf("getTableColumnInfo_pg err2:%w", err)
		}
		ret = append(ret, ColumnInfo{
			Name:     r.Field,
			Nullable: (!r.NotNull),
			Type:     r.Type,
		})
	}
	return ret, nil
}

func makePGDatabase(db dbCfg, dbname string) (c checkDbInfo, e error) {
	psqlInfo := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", db.Host, db.Port, db.User, db.Pwd, dbname)
	dbo, err := sql.Open("postgres", psqlInfo)
	if err != nil {
		return c, fmt.Errorf("open pg(%s) err:%s", dbname, err.Error())
	}
	err = checkDBPing(dbo)
	if err != nil {
		return c, fmt.Errorf("checkDBPing(%s) pg err:%s", dbname, err.Error())
	}
	return checkDbInfo{dbo, db_pg, dbname}, nil
}
