package aceboot::orm.postgres

import std.collection.*
import aceboot::orm.common.*

/** PostgreSQL 方言:占位 "$n",自增 `SERIAL PRIMARY KEY`,RETURNING 取 id。 */
public class PostgresDialect <: Dialect {
    public func placeholder(index: Int64): String {
        "$" + (index + 1).toString()
    }
    public func usesReturning(): Bool {
        true
    }
    public func sqlType(t: DbType): String {
        match (t) {
            case TInt => "INTEGER"
            case TBool => "BOOLEAN"
            case TReal => "DOUBLE PRECISION"
            case TText => "TEXT"
            case TDateTime => "BIGINT"
            case TDate => "BIGINT"
            case TJson => "JSONB"
            case TBlob => "BYTEA"
            case TDecimal => "NUMERIC"
        }
    }
    public func createTable(table: String, cols: Array<ColumnSpec>, checks: Array<CheckSpec>): String {
        buildCreateTable(table, cols, {name => name + " SERIAL PRIMARY KEY"}, {t => sqlType(t)}, checks: checks)
    }
    public func createIndex(table: String, idx: IndexSpec): String {
        buildCreateIndex(table, idx, true)
    }
    public func upsertClause(conflictColumns: Array<String>, updateColumns: Array<String>): String {
        onConflictClause(conflictColumns, updateColumns)
    }
    public func alterColumnType(table: String, col: ColumnSpec): ?String {
        Some("ALTER TABLE " + table + " ALTER COLUMN " + col.name + " TYPE " + columnType(col, {t => sqlType(t)}))
    }
    public func columnTypeMatches(currentRaw: String, target: ColumnSpec): Bool {
        normalizeSqlType(currentRaw) == normalizeSqlType(columnType(target, {t => sqlType(t)}))
    }
    // PG 列注释走独立语句(须在 CREATE TABLE 之后发,表已存在)。用 ArrayList 累积(勿闭包重赋 var)。
    public func columnComments(table: String, cols: Array<ColumnSpec>): Array<String> {
        let out = ArrayList<String>()
        for (c in cols) {
            if (c.comment != "") {
                out.add("COMMENT ON COLUMN " + table + "." + c.name + " IS " + sqlStringLiteral(c.comment))
            }
        }
        out.toArray()
    }
}