mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
955 lines
28 KiB
Go
955 lines
28 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package pgsql_test
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/test/gtest"
|
|
)
|
|
|
|
// Test_TableFields tests the TableFields method for retrieving table field information
|
|
func Test_TableFields(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
fields, err := db.TableFields(ctx, table)
|
|
t.AssertNil(err)
|
|
t.Assert(len(fields) > 0, true)
|
|
|
|
// Test primary key field
|
|
t.Assert(fields["id"].Name, "id")
|
|
t.Assert(fields["id"].Key, "pri")
|
|
|
|
// Test integer types
|
|
t.Assert(fields["col_int2"].Name, "col_int2")
|
|
t.Assert(fields["col_int4"].Name, "col_int4")
|
|
t.Assert(fields["col_int8"].Name, "col_int8")
|
|
|
|
// Test float types
|
|
t.Assert(fields["col_float4"].Name, "col_float4")
|
|
t.Assert(fields["col_float8"].Name, "col_float8")
|
|
t.Assert(fields["col_numeric"].Name, "col_numeric")
|
|
|
|
// Test character types
|
|
t.Assert(fields["col_char"].Name, "col_char")
|
|
t.Assert(fields["col_varchar"].Name, "col_varchar")
|
|
t.Assert(fields["col_text"].Name, "col_text")
|
|
|
|
// Test boolean type
|
|
t.Assert(fields["col_bool"].Name, "col_bool")
|
|
|
|
// Test date/time types
|
|
t.Assert(fields["col_date"].Name, "col_date")
|
|
t.Assert(fields["col_timestamp"].Name, "col_timestamp")
|
|
|
|
// Test JSON types
|
|
t.Assert(fields["col_json"].Name, "col_json")
|
|
t.Assert(fields["col_jsonb"].Name, "col_jsonb")
|
|
|
|
// Test array types
|
|
t.Assert(fields["col_int2_arr"].Name, "col_int2_arr")
|
|
t.Assert(fields["col_int4_arr"].Name, "col_int4_arr")
|
|
t.Assert(fields["col_varchar_arr"].Name, "col_varchar_arr")
|
|
})
|
|
}
|
|
|
|
// Test_TableFields_Types tests field type information
|
|
func Test_TableFields_Types(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
fields, err := db.TableFields(ctx, table)
|
|
t.AssertNil(err)
|
|
|
|
// Test integer type names
|
|
t.Assert(fields["col_int2"].Type, "int2(16)")
|
|
t.Assert(fields["col_int4"].Type, "int4(32)")
|
|
t.Assert(fields["col_int8"].Type, "int8(64)")
|
|
|
|
// Test float type names
|
|
t.Assert(fields["col_float4"].Type, "float4(24)")
|
|
t.Assert(fields["col_float8"].Type, "float8(53)")
|
|
t.Assert(fields["col_numeric"].Type, "numeric(10)")
|
|
|
|
// Test character type names
|
|
t.Assert(fields["col_char"].Type, "bpchar(10)")
|
|
t.Assert(fields["col_varchar"].Type, "varchar(100)")
|
|
t.Assert(fields["col_text"].Type, "text")
|
|
|
|
// Test boolean type name
|
|
t.Assert(fields["col_bool"].Type, "bool")
|
|
|
|
// Test date/time type names
|
|
t.Assert(fields["col_date"].Type, "date")
|
|
t.Assert(fields["col_timestamp"].Type, "timestamp")
|
|
t.Assert(fields["col_timestamptz"].Type, "timestamptz")
|
|
|
|
// Test JSON type names
|
|
t.Assert(fields["col_json"].Type, "json")
|
|
t.Assert(fields["col_jsonb"].Type, "jsonb")
|
|
|
|
// Test array type names (PostgreSQL uses _ prefix for array types)
|
|
t.Assert(fields["col_int2_arr"].Type, "_int2")
|
|
t.Assert(fields["col_int4_arr"].Type, "_int4")
|
|
t.Assert(fields["col_int8_arr"].Type, "_int8")
|
|
t.Assert(fields["col_float4_arr"].Type, "_float4")
|
|
t.Assert(fields["col_float8_arr"].Type, "_float8")
|
|
t.Assert(fields["col_numeric_arr"].Type, "_numeric")
|
|
t.Assert(fields["col_varchar_arr"].Type, "_varchar")
|
|
t.Assert(fields["col_text_arr"].Type, "_text")
|
|
t.Assert(fields["col_bool_arr"].Type, "_bool")
|
|
})
|
|
}
|
|
|
|
// Test_TableFields_Nullable tests field nullable information
|
|
func Test_TableFields_Nullable(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
fields, err := db.TableFields(ctx, table)
|
|
t.AssertNil(err)
|
|
|
|
// NOT NULL fields should have Null = false
|
|
t.Assert(fields["col_int2"].Null, false)
|
|
t.Assert(fields["col_int4"].Null, false)
|
|
t.Assert(fields["col_numeric"].Null, false)
|
|
t.Assert(fields["col_varchar"].Null, false)
|
|
t.Assert(fields["col_bool"].Null, false)
|
|
t.Assert(fields["col_varchar_arr"].Null, false)
|
|
|
|
// Nullable fields should have Null = true
|
|
t.Assert(fields["col_int8"].Null, true)
|
|
t.Assert(fields["col_text"].Null, true)
|
|
t.Assert(fields["col_json"].Null, true)
|
|
})
|
|
}
|
|
|
|
// Test_TableFields_Comments tests field comment information
|
|
func Test_TableFields_Comments(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
fields, err := db.TableFields(ctx, table)
|
|
t.AssertNil(err)
|
|
|
|
// Test fields with comments
|
|
t.Assert(fields["id"].Comment, "Primary key ID")
|
|
t.Assert(fields["col_int2"].Comment, "int2 type (smallint)")
|
|
t.Assert(fields["col_int4"].Comment, "int4 type (integer)")
|
|
t.Assert(fields["col_int8"].Comment, "int8 type (bigint)")
|
|
t.Assert(fields["col_numeric"].Comment, "numeric type with precision")
|
|
t.Assert(fields["col_varchar"].Comment, "varchar type")
|
|
t.Assert(fields["col_bool"].Comment, "boolean type")
|
|
t.Assert(fields["col_timestamp"].Comment, "timestamp type")
|
|
t.Assert(fields["col_json"].Comment, "json type")
|
|
t.Assert(fields["col_jsonb"].Comment, "jsonb type")
|
|
|
|
// Test array field comments
|
|
t.Assert(fields["col_int2_arr"].Comment, "int2 array type (_int2)")
|
|
t.Assert(fields["col_int4_arr"].Comment, "int4 array type (_int4)")
|
|
t.Assert(fields["col_int8_arr"].Comment, "int8 array type (_int8)")
|
|
t.Assert(fields["col_numeric_arr"].Comment, "numeric array type (_numeric)")
|
|
t.Assert(fields["col_varchar_arr"].Comment, "varchar array type (_varchar)")
|
|
t.Assert(fields["col_text_arr"].Comment, "text array type (_text)")
|
|
})
|
|
}
|
|
|
|
// Test_Field_Type_Conversion tests type conversion for various PostgreSQL types
|
|
func Test_Field_Type_Conversion(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query a single record
|
|
one, err := db.Model(table).Where("id", 1).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
|
|
// Test integer type conversions
|
|
t.Assert(one["col_int2"].Int(), 1)
|
|
t.Assert(one["col_int4"].Int(), 10)
|
|
t.Assert(one["col_int8"].Int64(), int64(100))
|
|
|
|
// Test float type conversions
|
|
t.Assert(one["col_float4"].Float32() > 0, true)
|
|
t.Assert(one["col_float8"].Float64() > 0, true)
|
|
|
|
// Test string type conversions
|
|
t.AssertNE(one["col_varchar"].String(), "")
|
|
t.AssertNE(one["col_text"].String(), "")
|
|
|
|
// Test boolean type conversion
|
|
t.Assert(one["col_bool"].Bool(), false) // i=1, 1%2==0 is false
|
|
})
|
|
}
|
|
|
|
// Test_Field_Array_Type_Conversion tests array type conversion
|
|
func Test_Field_Array_Type_Conversion(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query a single record
|
|
one, err := db.Model(table).Where("id", 1).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
|
|
// Test integer array type conversions
|
|
int2Arr := one["col_int2_arr"].Ints()
|
|
t.Assert(len(int2Arr), 3)
|
|
t.Assert(int2Arr[0], 1)
|
|
t.Assert(int2Arr[1], 2)
|
|
t.Assert(int2Arr[2], 1)
|
|
|
|
int4Arr := one["col_int4_arr"].Ints()
|
|
t.Assert(len(int4Arr), 3)
|
|
t.Assert(int4Arr[0], 10)
|
|
t.Assert(int4Arr[1], 20)
|
|
t.Assert(int4Arr[2], 1)
|
|
|
|
int8Arr := one["col_int8_arr"].Int64s()
|
|
t.Assert(len(int8Arr), 3)
|
|
t.Assert(int8Arr[0], int64(100))
|
|
t.Assert(int8Arr[1], int64(200))
|
|
t.Assert(int8Arr[2], int64(1))
|
|
|
|
// Test string array type conversions
|
|
varcharArr := one["col_varchar_arr"].Strings()
|
|
t.Assert(len(varcharArr), 3)
|
|
t.Assert(varcharArr[0], "a")
|
|
t.Assert(varcharArr[1], "b")
|
|
t.Assert(varcharArr[2], "c1")
|
|
|
|
textArr := one["col_text_arr"].Strings()
|
|
t.Assert(len(textArr), 3)
|
|
t.Assert(textArr[0], "x")
|
|
t.Assert(textArr[1], "y")
|
|
t.Assert(textArr[2], "z1")
|
|
|
|
// Test boolean array type conversions
|
|
// col_bool_arr is '{true, false, %t}' where %t = i%2==0, for i=1 it's false
|
|
boolArr := one["col_bool_arr"].Bools()
|
|
t.Assert(len(boolArr), 3)
|
|
t.Assert(boolArr[0], true) // literal true
|
|
t.Assert(boolArr[1], false) // literal false
|
|
t.Assert(boolArr[2], false) // i=1, 1%2==0 is false
|
|
})
|
|
}
|
|
|
|
// Test_Field_Array_Insert tests inserting array data
|
|
func Test_Field_Array_Insert(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with array values
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_int2_arr": []int{1, 2, 3},
|
|
"col_int4_arr": []int{10, 20, 30},
|
|
"col_varchar_arr": []string{"a", "b", "c"},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
t.Assert(one["col_int2"].Int(), 1)
|
|
t.Assert(one["col_varchar"].String(), "test")
|
|
t.Assert(one["col_bool"].Bool(), true)
|
|
|
|
int2Arr := one["col_int2_arr"].Ints()
|
|
t.Assert(len(int2Arr), 3)
|
|
t.Assert(int2Arr[0], 1)
|
|
t.Assert(int2Arr[1], 2)
|
|
t.Assert(int2Arr[2], 3)
|
|
|
|
varcharArr := one["col_varchar_arr"].Strings()
|
|
t.Assert(len(varcharArr), 3)
|
|
t.Assert(varcharArr[0], "a")
|
|
t.Assert(varcharArr[1], "b")
|
|
t.Assert(varcharArr[2], "c")
|
|
})
|
|
}
|
|
|
|
// Test_Field_Array_Update tests updating array data
|
|
func Test_Field_Array_Update(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Update array values
|
|
_, err := db.Model(table).Where("id", 1).Data(g.Map{
|
|
"col_int2_arr": []int{100, 200, 300},
|
|
"col_varchar_arr": []string{"x", "y", "z"},
|
|
}).Update()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).Where("id", 1).One()
|
|
t.AssertNil(err)
|
|
|
|
int2Arr := one["col_int2_arr"].Ints()
|
|
t.Assert(len(int2Arr), 3)
|
|
t.Assert(int2Arr[0], 100)
|
|
t.Assert(int2Arr[1], 200)
|
|
t.Assert(int2Arr[2], 300)
|
|
|
|
varcharArr := one["col_varchar_arr"].Strings()
|
|
t.Assert(len(varcharArr), 3)
|
|
t.Assert(varcharArr[0], "x")
|
|
t.Assert(varcharArr[1], "y")
|
|
t.Assert(varcharArr[2], "z")
|
|
})
|
|
}
|
|
|
|
// Test_Field_JSON_Type tests JSON/JSONB type handling
|
|
func Test_Field_JSON_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with JSON values
|
|
testData := g.Map{
|
|
"name": "test",
|
|
"value": 123,
|
|
"items": []string{"a", "b", "c"},
|
|
}
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_json": testData,
|
|
"col_jsonb": testData,
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test JSON field
|
|
jsonMap := one["col_json"].Map()
|
|
t.Assert(jsonMap["name"], "test")
|
|
t.Assert(jsonMap["value"], 123)
|
|
|
|
// Test JSONB field
|
|
jsonbMap := one["col_jsonb"].Map()
|
|
t.Assert(jsonbMap["name"], "test")
|
|
t.Assert(jsonbMap["value"], 123)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Scan_To_Struct tests scanning results to struct
|
|
func Test_Field_Scan_To_Struct(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
type TestRecord struct {
|
|
Id int64 `json:"id"`
|
|
ColInt2 int16 `json:"col_int2"`
|
|
ColInt4 int32 `json:"col_int4"`
|
|
ColInt8 int64 `json:"col_int8"`
|
|
ColVarchar string `json:"col_varchar"`
|
|
ColBool bool `json:"col_bool"`
|
|
ColInt2Arr []int `json:"col_int2_arr"`
|
|
ColInt4Arr []int `json:"col_int4_arr"`
|
|
ColInt8Arr []int64 `json:"col_int8_arr"`
|
|
ColTextArr []string `json:"col_text_arr"`
|
|
}
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var record TestRecord
|
|
err := db.Model(table).Where("id", 1).Scan(&record)
|
|
t.AssertNil(err)
|
|
|
|
t.Assert(record.Id, int64(1))
|
|
t.Assert(record.ColInt2, int16(1))
|
|
t.Assert(record.ColInt4, int32(10))
|
|
t.Assert(record.ColInt8, int64(100))
|
|
t.AssertNE(record.ColVarchar, "")
|
|
t.Assert(record.ColBool, false)
|
|
|
|
// Test array fields scanned to struct
|
|
t.Assert(len(record.ColInt2Arr), 3)
|
|
t.Assert(record.ColInt2Arr[0], 1)
|
|
t.Assert(record.ColInt2Arr[1], 2)
|
|
t.Assert(record.ColInt2Arr[2], 1)
|
|
|
|
t.Assert(len(record.ColTextArr), 3)
|
|
t.Assert(record.ColTextArr[0], "x")
|
|
t.Assert(record.ColTextArr[1], "y")
|
|
t.Assert(record.ColTextArr[2], "z1")
|
|
})
|
|
}
|
|
|
|
// Test_Field_Scan_To_Struct_Slice tests scanning multiple results to struct slice
|
|
func Test_Field_Scan_To_Struct_Slice(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
type TestRecord struct {
|
|
Id int64 `json:"id"`
|
|
ColInt2 int16 `json:"col_int2"`
|
|
ColVarchar string `json:"col_varchar"`
|
|
ColInt2Arr []int `json:"col_int2_arr"`
|
|
ColTextArr []string `json:"col_text_arr"`
|
|
}
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
var records []TestRecord
|
|
err := db.Model(table).OrderAsc("id").Limit(5).Scan(&records)
|
|
t.AssertNil(err)
|
|
|
|
t.Assert(len(records), 5)
|
|
|
|
// Verify first record
|
|
t.Assert(records[0].Id, int64(1))
|
|
t.Assert(records[0].ColInt2, int16(1))
|
|
t.Assert(len(records[0].ColInt2Arr), 3)
|
|
|
|
// Verify last record
|
|
t.Assert(records[4].Id, int64(5))
|
|
t.Assert(records[4].ColInt2, int16(5))
|
|
})
|
|
}
|
|
|
|
// Test_Field_Empty_Array tests handling empty arrays
|
|
func Test_Field_Empty_Array(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with empty array values (using default)
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify empty arrays
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Default empty arrays
|
|
int2Arr := one["col_int2_arr"].Ints()
|
|
t.Assert(len(int2Arr), 0)
|
|
|
|
varcharArr := one["col_varchar_arr"].Strings()
|
|
t.Assert(len(varcharArr), 0)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Null_Values tests handling NULL values
|
|
func Test_Field_Null_Values(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert minimal required fields, leaving nullable fields as NULL
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify NULL handling
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Nullable fields should return appropriate zero values
|
|
t.Assert(one["col_text"].IsNil() || one["col_text"].IsEmpty(), true)
|
|
t.Assert(one["col_int8_arr"].IsNil() || one["col_int8_arr"].IsEmpty(), true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Float_Array_Type_Conversion tests float array type conversion (_float4, _float8)
|
|
func Test_Field_Float_Array_Type_Conversion(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query a single record
|
|
one, err := db.Model(table).Where("id", 1).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
|
|
// Test float4 array type conversions
|
|
float4Arr := one["col_float4_arr"].Float32s()
|
|
t.Assert(len(float4Arr), 3)
|
|
t.Assert(float4Arr[0] > 0, true)
|
|
t.Assert(float4Arr[1] > 0, true)
|
|
|
|
// Test float8 array type conversions
|
|
float8Arr := one["col_float8_arr"].Float64s()
|
|
t.Assert(len(float8Arr), 3)
|
|
t.Assert(float8Arr[0] > 0, true)
|
|
t.Assert(float8Arr[1] > 0, true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Numeric_Array_Type_Conversion tests numeric/decimal array type conversion
|
|
func Test_Field_Numeric_Array_Type_Conversion(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query a single record
|
|
one, err := db.Model(table).Where("id", 1).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
|
|
// Test numeric array type conversions
|
|
numericArr := one["col_numeric_arr"].Float64s()
|
|
t.Assert(len(numericArr), 3)
|
|
t.Assert(numericArr[0] > 0, true)
|
|
t.Assert(numericArr[1] > 0, true)
|
|
|
|
// Test decimal array type conversions
|
|
decimalArr := one["col_decimal_arr"].Float64s()
|
|
if !one["col_decimal_arr"].IsNil() {
|
|
t.Assert(len(decimalArr) > 0, true)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test_Field_Bool_Array_Type_Conversion tests bool array type conversion more thoroughly
|
|
func Test_Field_Bool_Array_Type_Conversion(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with specific bool array values
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_bool_arr": []bool{true, false, true},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test bool array
|
|
boolArr := one["col_bool_arr"].Bools()
|
|
t.Assert(len(boolArr), 3)
|
|
t.Assert(boolArr[0], true)
|
|
t.Assert(boolArr[1], false)
|
|
t.Assert(boolArr[2], true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Char_Array_Type tests char array type (_char)
|
|
func Test_Field_Char_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with char array values
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_char_arr": []string{"a", "b", "c"},
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test char array
|
|
charArr := one["col_char_arr"].Strings()
|
|
t.Assert(len(charArr), 3)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Bytea_Type tests bytea (binary) type conversion
|
|
func Test_Field_Bytea_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with binary data
|
|
binaryData := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f} // "Hello" in hex
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_bytea": binaryData,
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test bytea field
|
|
result := one["col_bytea"].Bytes()
|
|
t.Assert(len(result), 5)
|
|
t.Assert(result[0], 0x48) // 'H'
|
|
})
|
|
}
|
|
|
|
// Test_Field_Bytea_Array_Type tests bytea array type (_bytea)
|
|
func Test_Field_Bytea_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with bytea array values using raw SQL
|
|
// PostgreSQL bytea array literal format: ARRAY[E'\\x010203', E'\\x040506']::bytea[]
|
|
_, err := db.Exec(ctx, fmt.Sprintf(`
|
|
INSERT INTO %s (col_int2, col_int4, col_numeric, col_varchar, col_bool, col_varchar_arr, col_bytea_arr)
|
|
VALUES (1, 10, 99.99, 'test', true, '{}', ARRAY[E'\\x010203', E'\\x040506']::bytea[])
|
|
`, table))
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify bytea array
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test bytea array field - should be converted to [][]byte
|
|
byteaArrVal := one["col_bytea_arr"]
|
|
t.Assert(byteaArrVal.IsNil(), false)
|
|
|
|
// Verify the array contains the expected data
|
|
byteaArr := byteaArrVal.Interfaces()
|
|
t.Assert(len(byteaArr), 2)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Date_Array_Type tests date array type (_date)
|
|
func Test_Field_Date_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Note: PostgreSQL _date array is not yet mapped in the driver
|
|
// This test documents the limitation but can be extended when support is added
|
|
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify NULL date array is handled gracefully
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
// date array should be nil or empty
|
|
t.Assert(one["col_date_arr"].IsNil() || one["col_date_arr"].IsEmpty(), true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Timestamp_Array_Type tests timestamp array type (_timestamp)
|
|
func Test_Field_Timestamp_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Note: PostgreSQL _timestamp array is not yet mapped in the driver
|
|
// This test documents the limitation but can be extended when support is added
|
|
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify NULL timestamp array is handled gracefully
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
// timestamp array should be nil or empty
|
|
t.Assert(one["col_timestamp_arr"].IsNil() || one["col_timestamp_arr"].IsEmpty(), true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_JSONB_Array_Type tests JSONB array type (_jsonb)
|
|
func Test_Field_JSONB_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Note: PostgreSQL _jsonb array is not yet mapped in the driver
|
|
// This test documents the limitation but can be extended when support is added
|
|
|
|
_, err := db.Model(table).Data(g.Map{
|
|
"col_int2": 1,
|
|
"col_int4": 10,
|
|
"col_numeric": 99.99,
|
|
"col_varchar": "test",
|
|
"col_bool": true,
|
|
"col_varchar_arr": []string{},
|
|
}).Insert()
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify NULL jsonb array is handled gracefully
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
// jsonb array should be nil or empty
|
|
t.Assert(one["col_jsonb_arr"].IsNil() || one["col_jsonb_arr"].IsEmpty(), true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_UUID_Array_Type tests UUID array type (_uuid)
|
|
func Test_Field_UUID_Array_Type(t *testing.T) {
|
|
table := createAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Insert with UUID array values using raw SQL
|
|
// PostgreSQL uuid array literal format: ARRAY['uuid1', 'uuid2']::uuid[]
|
|
uuid1 := "550e8400-e29b-41d4-a716-446655440000"
|
|
uuid2 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
|
uuid3 := "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
|
|
_, err := db.Exec(ctx, fmt.Sprintf(`
|
|
INSERT INTO %s (col_int2, col_int4, col_numeric, col_varchar, col_bool, col_varchar_arr, col_uuid_arr)
|
|
VALUES (1, 10, 99.99, 'test', true, '{}', ARRAY['%s', '%s', '%s']::uuid[])
|
|
`, table, uuid1, uuid2, uuid3))
|
|
t.AssertNil(err)
|
|
|
|
// Query and verify UUID array
|
|
one, err := db.Model(table).OrderDesc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test UUID array field - should be converted to []uuid.UUID
|
|
uuidArrVal := one["col_uuid_arr"]
|
|
t.Assert(uuidArrVal.IsNil(), false)
|
|
|
|
// Verify the array contains the expected data as []uuid.UUID
|
|
uuidArr := uuidArrVal.Interfaces()
|
|
t.Assert(len(uuidArr), 3)
|
|
|
|
// Verify each element is uuid.UUID type
|
|
u1, ok := uuidArr[0].(uuid.UUID)
|
|
t.Assert(ok, true)
|
|
t.Assert(u1.String(), uuid1)
|
|
|
|
u2, ok := uuidArr[1].(uuid.UUID)
|
|
t.Assert(ok, true)
|
|
t.Assert(u2.String(), uuid2)
|
|
|
|
u3, ok := uuidArr[2].(uuid.UUID)
|
|
t.Assert(ok, true)
|
|
t.Assert(u3.String(), uuid3)
|
|
})
|
|
}
|
|
|
|
// Test_Field_UUID_Type tests UUID type
|
|
func Test_Field_UUID_Type(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query and verify UUID field
|
|
one, err := db.Model(table).OrderAsc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test UUID field - should be converted to uuid.UUID
|
|
uuidVal := one["col_uuid"]
|
|
t.Assert(uuidVal.IsNil(), false)
|
|
|
|
// Verify the value is uuid.UUID type
|
|
uuidObj, ok := uuidVal.Val().(uuid.UUID)
|
|
t.Assert(ok, true)
|
|
|
|
// Verify the UUID format
|
|
uuidStr := uuidObj.String()
|
|
t.Assert(len(uuidStr) > 0, true)
|
|
// UUID should contain the pattern from insert: 550e8400-e29b-41d4-a716-44665544000X
|
|
t.Assert(uuidStr, "550e8400-e29b-41d4-a716-446655440001")
|
|
|
|
// Also verify we can still get string representation via .String()
|
|
t.Assert(uuidVal.String(), "550e8400-e29b-41d4-a716-446655440001")
|
|
})
|
|
}
|
|
|
|
// Test_Field_Bytea_Array_Type_Scan tests bytea array type and scanning
|
|
func Test_Field_Bytea_Array_Type_Scan(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query and verify bytea array field
|
|
one, err := db.Model(table).OrderAsc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test bytea array field
|
|
byteaArrVal := one["col_bytea_arr"]
|
|
// bytea array should not be nil since we inserted data
|
|
t.Assert(byteaArrVal.IsNil(), false)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Date_Array_Type_Scan tests date array type and scanning
|
|
func Test_Field_Date_Array_Type_Scan(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query and verify date array field
|
|
one, err := db.Model(table).OrderAsc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test date array field
|
|
dateArrVal := one["col_date_arr"]
|
|
t.Assert(dateArrVal.IsNil(), false)
|
|
|
|
// Verify the array contains the expected data
|
|
dateArr := dateArrVal.Strings()
|
|
t.Assert(len(dateArr) > 0, true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_Timestamp_Array_Type_Scan tests timestamp array type and scanning
|
|
func Test_Field_Timestamp_Array_Type_Scan(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query and verify timestamp array field
|
|
one, err := db.Model(table).OrderAsc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test timestamp array field
|
|
timestampArrVal := one["col_timestamp_arr"]
|
|
t.Assert(timestampArrVal.IsNil(), false)
|
|
|
|
// Verify the array contains the expected data
|
|
timestampArr := timestampArrVal.Strings()
|
|
t.Assert(len(timestampArr) > 0, true)
|
|
})
|
|
}
|
|
|
|
// Test_Field_JSONB_Array_Type_Scan tests JSONB array type and scanning
|
|
func Test_Field_JSONB_Array_Type_Scan(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Query and verify JSONB array field
|
|
one, err := db.Model(table).OrderAsc("id").One()
|
|
t.AssertNil(err)
|
|
|
|
// Test JSONB array field
|
|
jsonbArrVal := one["col_jsonb_arr"]
|
|
t.Assert(jsonbArrVal.IsNil(), false)
|
|
})
|
|
}
|
|
|
|
// Test_Field_UUID_Query tests querying by UUID field
|
|
func Test_Field_UUID_Query(t *testing.T) {
|
|
table := createInitAllTypesTable()
|
|
defer dropTable(table)
|
|
|
|
gtest.C(t, func(t *gtest.T) {
|
|
// Test 1: Query by UUID string
|
|
uuidStr := "550e8400-e29b-41d4-a716-446655440001"
|
|
one, err := db.Model(table).Where("col_uuid", uuidStr).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
t.Assert(one["id"].Int(), 1)
|
|
|
|
// Verify the returned UUID is correct
|
|
uuidObj, ok := one["col_uuid"].Val().(uuid.UUID)
|
|
t.Assert(ok, true)
|
|
t.Assert(uuidObj.String(), uuidStr)
|
|
|
|
// Test 2: Query by uuid.UUID type directly
|
|
uuidVal, err := uuid.Parse("550e8400-e29b-41d4-a716-446655440002")
|
|
t.AssertNil(err)
|
|
one, err = db.Model(table).Where("col_uuid", uuidVal).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
t.Assert(one["id"].Int(), 2)
|
|
|
|
// Test 3: Query by UUID string using g.Map
|
|
one, err = db.Model(table).Where(g.Map{
|
|
"col_uuid": "550e8400-e29b-41d4-a716-446655440003",
|
|
}).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
t.Assert(one["id"].Int(), 3)
|
|
|
|
// Test 4: Query by uuid.UUID type using g.Map
|
|
uuidVal, err = uuid.Parse("550e8400-e29b-41d4-a716-446655440004")
|
|
t.AssertNil(err)
|
|
one, err = db.Model(table).Where(g.Map{
|
|
"col_uuid": uuidVal,
|
|
}).One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), false)
|
|
t.Assert(one["id"].Int(), 4)
|
|
|
|
// Test 5: Query non-existent UUID
|
|
one, err = db.Model(table).Where("col_uuid", "00000000-0000-0000-0000-000000000000").One()
|
|
t.AssertNil(err)
|
|
t.Assert(one.IsEmpty(), true)
|
|
|
|
// Test 6: Query multiple records by UUID IN clause with strings
|
|
all, err := db.Model(table).WhereIn("col_uuid", g.Slice{
|
|
"550e8400-e29b-41d4-a716-446655440001",
|
|
"550e8400-e29b-41d4-a716-446655440002",
|
|
}).OrderAsc("id").All()
|
|
t.AssertNil(err)
|
|
t.Assert(len(all), 2)
|
|
t.Assert(all[0]["id"].Int(), 1)
|
|
t.Assert(all[1]["id"].Int(), 2)
|
|
|
|
// Test 7: Query multiple records by UUID IN clause with uuid.UUID types
|
|
uuid1, _ := uuid.Parse("550e8400-e29b-41d4-a716-446655440003")
|
|
uuid2, _ := uuid.Parse("550e8400-e29b-41d4-a716-446655440004")
|
|
all, err = db.Model(table).WhereIn("col_uuid", g.Slice{uuid1, uuid2}).OrderAsc("id").All()
|
|
t.AssertNil(err)
|
|
t.Assert(len(all), 2)
|
|
t.Assert(all[0]["id"].Int(), 3)
|
|
t.Assert(all[1]["id"].Int(), 4)
|
|
})
|
|
}
|