Skip to content

Commit d987665

Browse files
Adding test
1 parent d8da090 commit d987665

File tree

1 file changed

+193
-0
lines changed

1 file changed

+193
-0
lines changed

tests/json_bulk_test.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
** Copyright (c) 2025 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package tests
40+
41+
import (
42+
"encoding/json"
43+
"errors"
44+
"testing"
45+
46+
"gorm.io/datatypes"
47+
"gorm.io/gorm"
48+
"gorm.io/gorm/clause"
49+
)
50+
51+
func TestBasicCRUD_JSONText(t *testing.T) {
52+
type JsonRecord struct {
53+
ID uint `gorm:"primaryKey;autoIncrement;column:record_id"`
54+
Name string `gorm:"column:name"`
55+
Properties datatypes.JSON `gorm:"column:properties"`
56+
}
57+
58+
DB.Migrator().DropTable(&JsonRecord{})
59+
if err := DB.AutoMigrate(&JsonRecord{}); err != nil {
60+
t.Fatalf("migrate failed: %v", err)
61+
}
62+
63+
// INSERT
64+
rec := JsonRecord{
65+
Name: "json-text",
66+
Properties: datatypes.JSON([]byte(`{"env":"prod","owner":"team-x"}`)),
67+
}
68+
if err := DB.Create(&rec).Error; err != nil {
69+
t.Fatalf("create failed: %v", err)
70+
}
71+
if rec.ID == 0 {
72+
t.Fatalf("expected ID to be set")
73+
}
74+
75+
// UPDATE (with RETURNING)
76+
var ret JsonRecord
77+
if err := DB.
78+
Clauses(clause.Returning{
79+
Columns: []clause.Column{
80+
{Name: "record_id"},
81+
{Name: "name"},
82+
{Name: "properties"},
83+
},
84+
}).
85+
Model(&ret).
86+
Where("\"record_id\" = ?", rec.ID).
87+
Updates(map[string]any{
88+
"name": "json-text-upd",
89+
"properties": datatypes.JSON([]byte(`{"env":"staging","owner":"team-y","flag":true}`)),
90+
}).Error; err != nil {
91+
t.Fatalf("update returning failed: %v", err)
92+
}
93+
if ret.ID != rec.ID || ret.Name != "json-text-upd" || len(ret.Properties) == 0 {
94+
t.Fatalf("unexpected returning row: %#v", ret)
95+
}
96+
97+
// DELETE (with RETURNING)
98+
var deleted []JsonRecord
99+
if err := DB.
100+
Where("\"record_id\" = ?", rec.ID).
101+
Clauses(clause.Returning{
102+
Columns: []clause.Column{
103+
{Name: "record_id"},
104+
{Name: "name"},
105+
{Name: "properties"},
106+
},
107+
}).
108+
Delete(&deleted).Error; err != nil {
109+
t.Fatalf("delete returning failed: %v", err)
110+
}
111+
if len(deleted) != 1 || deleted[0].ID != rec.ID {
112+
t.Fatalf("unexpected deleted rows: %#v", deleted)
113+
}
114+
115+
// verify gone
116+
var check JsonRecord
117+
err := DB.First(&check, "\"record_id\" = ?", rec.ID).Error
118+
if !errors.Is(err, gorm.ErrRecordNotFound) {
119+
t.Fatalf("expected not found after delete, got: %v", err)
120+
}
121+
}
122+
123+
func TestBasicCRUD_RawMessage(t *testing.T) {
124+
type RawRecord struct {
125+
ID uint `gorm:"primaryKey;autoIncrement;column:record_id"`
126+
Name string `gorm:"column:name"`
127+
Properties json.RawMessage `gorm:"column:properties"`
128+
}
129+
130+
DB.Migrator().DropTable(&RawRecord{})
131+
if err := DB.AutoMigrate(&RawRecord{}); err != nil {
132+
t.Fatalf("migrate failed: %v", err)
133+
}
134+
135+
// INSERT
136+
rec := RawRecord{
137+
Name: "raw-json",
138+
Properties: json.RawMessage(`{"a":1,"b":"x"}`),
139+
}
140+
if err := DB.Create(&rec).Error; err != nil {
141+
t.Fatalf("create failed: %v", err)
142+
}
143+
if rec.ID == 0 {
144+
t.Fatalf("expected ID to be set")
145+
}
146+
147+
// UPDATE (with RETURNING)
148+
var ret RawRecord
149+
if err := DB.
150+
Clauses(clause.Returning{
151+
Columns: []clause.Column{
152+
{Name: "record_id"},
153+
{Name: "name"},
154+
{Name: "properties"},
155+
},
156+
}).
157+
Model(&ret).
158+
Where("\"record_id\" = ?", rec.ID).
159+
Updates(map[string]any{
160+
"name": "raw-json-upd",
161+
"properties": json.RawMessage(`{"a":2,"c":true}`),
162+
}).Error; err != nil {
163+
t.Fatalf("update returning failed: %v", err)
164+
}
165+
if ret.ID != rec.ID || ret.Name != "raw-json-upd" || len(ret.Properties) == 0 {
166+
t.Fatalf("unexpected returning row: %#v", ret)
167+
}
168+
169+
// DELETE (with RETURNING)
170+
var deleted []RawRecord
171+
if err := DB.
172+
Where("\"record_id\" = ?", rec.ID).
173+
Clauses(clause.Returning{
174+
Columns: []clause.Column{
175+
{Name: "record_id"},
176+
{Name: "name"},
177+
{Name: "properties"},
178+
},
179+
}).
180+
Delete(&deleted).Error; err != nil {
181+
t.Fatalf("delete returning failed: %v", err)
182+
}
183+
if len(deleted) != 1 || deleted[0].ID != rec.ID {
184+
t.Fatalf("unexpected deleted rows: %#v", deleted)
185+
}
186+
187+
// verify gone
188+
var check RawRecord
189+
err := DB.First(&check, "\"record_id\" = ?", rec.ID).Error
190+
if !errors.Is(err, gorm.ErrRecordNotFound) {
191+
t.Fatalf("expected not found after delete, got: %v", err)
192+
}
193+
}

0 commit comments

Comments
 (0)