st_sqlConn_CanThrowUniqueConstraintViolationError   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nop 1
dl 0
loc 18
rs 9.85
c 0
b 0
f 0
1
package sqladapter_test
2
3
import (
4
	"database/sql"
5
	"fmt"
6
	"testing"
7
	"time"
8
9
	"github.com/cdleo/go-commons/sqlcommons"
10
	adapter "github.com/cdleo/go-sql-adapter"
11
	"github.com/cdleo/go-sql-adapter/engines"
12
	enginesMocks "github.com/cdleo/go-sql-adapter/engines/mocks"
13
	"github.com/cdleo/go-sql-adapter/translators"
14
	"github.com/stretchr/testify/require"
15
)
16
17
type Customers struct {
18
	Id         int           `db:"id"`
19
	Name       string        `db:"name"`
20
	Updatetime time.Time     `db:"updatetime"`
21
	Age        sql.NullInt64 `db:"age"`
22
	Group      int           `db:"cust_group"`
23
	Dummy      string        `db:"not_existing_field"`
24
}
25
26
func Test_sqlConn_InitErr(t *testing.T) {
27
	// Setup
28
	connector := enginesMocks.NewMockSQLConnector(false)
29
	translator := translators.NewNoopTranslator()
30
31
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
32
	_, err := sqlConn.Open()
33
	require.Error(t, err)
34
}
35
36
func Test_sqlConn_InitOK(t *testing.T) {
37
	// Setup
38
	connector := enginesMocks.NewMockSQLConnector(true)
39
	translator := translators.NewNoopTranslator()
40
41
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
42
	_, err := sqlConn.Open()
43
	require.NoError(t, err)
44
}
45
46
func Test_sqlConn_CreateTables(t *testing.T) {
47
	// Setup
48
	connector := engines.NewSqlite3Connector(":memory:")
49
	translator := translators.NewNoopTranslator()
50
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
51
52
	db, err := sqlConn.Open()
53
	require.NoError(t, err)
54
55
	// Exec
56
	require.NoError(t, createTablesHelper(db))
57
58
	db.Close()
59
}
60
61
func Test_sqlConn_DropTables(t *testing.T) {
62
	// Setup
63
	connector := engines.NewSqlite3Connector(":memory:")
64
	translator := translators.NewNoopTranslator()
65
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
66
67
	db, err := sqlConn.Open()
68
	require.NoError(t, err)
69
	require.NoError(t, createTablesHelper(db))
70
71
	// Exec
72
	require.NoError(t, dropTablesHelper(db))
73
74
	db.Close()
75
}
76
77
func Test_sqlConn_StoreData(t *testing.T) {
78
	// Setup
79
	connector := engines.NewSqlite3Connector(":memory:")
80
	translator := translators.NewNoopTranslator()
81
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
82
83
	db, err := sqlConn.Open()
84
	require.NoError(t, err)
85
86
	require.NoError(t, createTablesHelper(db))
87
88
	// Exec
89
	require.NoError(t, insertDataHelper(db))
90
91
	db.Close()
92
}
93
94
func Test_sqlConn_ReturnData(t *testing.T) {
95
	// Setup
96
	connector := engines.NewSqlite3Connector(":memory:")
97
	translator := translators.NewNoopTranslator()
98
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
99
100
	db, err := sqlConn.Open()
101
	require.NoError(t, err)
102
103
	require.NoError(t, createTablesHelper(db))
104
	require.NoError(t, insertDataHelper(db))
105
106
	// Exec
107
	rows, err2 := db.Query("SELECT name FROM customers")
108
	defer rows.Close()
109
110
	require.NoError(t, err2)
111
	require.True(t, rows.Next())
112
113
	db.Close()
114
}
115
116
func Test_sqlConn_CanThrowInvalidTableError(t *testing.T) {
117
	// Setup
118
	connector := engines.NewSqlite3Connector(":memory:")
119
	translator := translators.NewNoopTranslator()
120
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
121
122
	db, err := sqlConn.Open()
123
	require.NoError(t, err)
124
125
	require.NoError(t, createTablesHelper(db))
126
	require.NoError(t, insertDataHelper(db))
127
128
	// Exec
129
	_, err2 := db.Query("SELECT name FROM customerxs")
130
131
	require.Error(t, err2)
132
133
	db.Close()
134
}
135
136
func Test_sqlConn_CanThrowCannotInsertNullError(t *testing.T) {
137
	// Setup
138
	connector := engines.NewSqlite3Connector(":memory:")
139
	translator := translators.NewNoopTranslator()
140
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
141
142
	db, err := sqlConn.Open()
143
	require.NoError(t, err)
144
145
	require.NoError(t, createTablesHelper(db))
146
147
	// Exec
148
	_, err2 := db.Exec("INSERT INTO customers (name, updatetime) VALUES (:1,:2)", nil, time.Now())
149
150
	require.ErrorIs(t, err2, sqlcommons.CannotSetNullColumn)
151
152
	db.Close()
153
}
154
155
func Test_sqlConn_CanThrowCannotUpdateNullError(t *testing.T) {
156
	// Setup
157
	connector := engines.NewSqlite3Connector(":memory:")
158
	translator := translators.NewNoopTranslator()
159
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
160
161
	db, err := sqlConn.Open()
162
	require.NoError(t, err)
163
164
	require.NoError(t, createTablesHelper(db))
165
	require.NoError(t, insertDataHelper(db))
166
167
	// Exec
168
	_, err2 := db.Exec("UPDATE customers c SET name = :1 WHERE c.name = :2", nil, "Pablo")
169
170
	require.Error(t, err2, sqlcommons.CannotSetNullColumn)
171
172
	db.Close()
173
}
174
175
func Test_sqlConn_CanThrowUniqueConstraintViolationError(t *testing.T) {
176
	// Setup
177
	connector := engines.NewSqlite3Connector(":memory:?_foreign_keys=on")
178
	translator := translators.NewNoopTranslator()
179
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
180
181
	db, err := sqlConn.Open()
182
	require.NoError(t, err)
183
184
	require.NoError(t, createTablesHelper(db))
185
	require.NoError(t, insertDataHelper(db))
186
187
	// Exec
188
	_, err2 := db.Exec("INSERT INTO customers (name, updatetime, age, cust_group)VALUES(:1, :2, :3, :4)", "Juan", time.Now(), nil, 1)
189
190
	require.ErrorIs(t, err2, sqlcommons.UniqueConstraintViolation)
191
192
	db.Close()
193
}
194
195
func Test_sqlConn_CanThrowForeignKeyConstraintViolationError(t *testing.T) {
196
	// Setup
197
	connector := engines.NewSqlite3Connector(":memory:?_foreign_keys=on")
198
	translator := translators.NewNoopTranslator()
199
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
200
201
	db, err := sqlConn.Open()
202
	require.NoError(t, err)
203
204
	require.NoError(t, createTablesHelper(db))
205
	require.NoError(t, insertDataHelper(db))
206
207
	// Exec
208
	_, err2 := db.Exec("UPDATE customers SET cust_group = :1 WHERE name = :2", 2, "Pablo")
209
210
	require.ErrorIs(t, err2, sqlcommons.IntegrityConstraintViolation)
211
212
	db.Close()
213
}
214
215
func Test_sqlConn_CanThrowIntegrityConstraintViolationError(t *testing.T) {
216
	// Setup
217
	connector := engines.NewSqlite3Connector(":memory:?_foreign_keys=on")
218
	translator := translators.NewNoopTranslator()
219
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
220
221
	db, err := sqlConn.Open()
222
	require.NoError(t, err)
223
224
	require.NoError(t, createTablesHelper(db))
225
	require.NoError(t, insertDataHelper(db))
226
227
	// Exec
228
	_, err2 := db.Exec("DELETE from customers_groups WHERE id = :1", 1)
229
230
	require.ErrorIs(t, err2, sqlcommons.IntegrityConstraintViolation)
231
232
	db.Close()
233
}
234
235
func Test_sqlConn_CanThrowValueTooLargeError(t *testing.T) {
236
	// Setup
237
	connector := enginesMocks.NewMockSQLConnector(true)
238
	translator := translators.NewNoopTranslator()
239
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
240
241
	db, err := sqlConn.Open()
242
	require.NoError(t, err)
243
244
	// Exec
245
	query := fmt.Sprintf("INSERT INTO customers (name, cust_group) VALUES (%s,%d)", "'verylongname'", 1)
246
	connector.PatchExec(query, sqlcommons.ValueTooLargeForColumn)
247
248
	_, err2 := db.Exec(query)
249
250
	require.ErrorIs(t, err2, sqlcommons.ValueTooLargeForColumn)
251
252
	db.Close()
253
}
254
255
func Test_sqlConn_CanThrowSubqueryReturnsMoreThanOneRowError(t *testing.T) {
256
	// Setup
257
	connector := enginesMocks.NewMockSQLConnector(true)
258
	translator := translators.NewNoopTranslator()
259
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
260
261
	db, err := sqlConn.Open()
262
	require.NoError(t, err)
263
264
	query := "SELECT name FROM customers WHERE id = (SELECT id FROM customers)"
265
	connector.PatchQuery(query, nil, nil, sqlcommons.SubqueryReturnsMoreThanOneRow)
266
267
	// Exec
268
	_, err2 := db.Query(query)
269
270
	require.ErrorIs(t, err2, sqlcommons.SubqueryReturnsMoreThanOneRow)
271
272
	db.Close()
273
}
274
275
func Test_sqlConn_CanThrowInvalidNumericValueError(t *testing.T) {
276
	// Setup
277
	connector := enginesMocks.NewMockSQLConnector(true)
278
	translator := translators.NewNoopTranslator()
279
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
280
281
	db, err := sqlConn.Open()
282
	require.NoError(t, err)
283
284
	query := "UPDATE customers SET age = :1 WHERE name = :2"
285
	connector.PatchExec(query, sqlcommons.InvalidNumericValue, "twelve", "Pablo")
286
287
	// Exec
288
	_, err2 := db.Exec(query, "twelve", "Pablo")
289
290
	require.ErrorIs(t, err2, sqlcommons.InvalidNumericValue)
291
292
	db.Close()
293
}
294
295
func Test_sqlConn_CanThrowValueLargerThanPrecisionError(t *testing.T) {
296
	// Setup
297
	connector := enginesMocks.NewMockSQLConnector(true)
298
	translator := translators.NewNoopTranslator()
299
	sqlConn := adapter.NewSQLAdapter(connector, translator, nil)
300
301
	db, err := sqlConn.Open()
302
	require.NoError(t, err)
303
304
	query := "UPDATE customers SET age = :1 WHERE name = :2"
305
	connector.PatchExec(query, sqlcommons.ValueLargerThanPrecision, 949.0044, "Pablo")
306
307
	// Exec
308
	_, err2 := db.Exec(query, 949.0044, "Pablo")
309
310
	require.ErrorIs(t, err2, sqlcommons.ValueLargerThanPrecision)
311
312
	db.Close()
313
}
314
315
func dropTablesHelper(db *sql.DB) error {
316
317
	if _, err := db.Exec(`DROP TABLE IF EXISTS customers_groups`); err != nil {
318
		return err
319
	}
320
	if _, err := db.Exec(`DROP TABLE IF EXISTS customers`); err != nil {
321
		return err
322
	}
323
	return nil
324
}
325
326
func createTablesHelper(db *sql.DB) error {
327
328
	if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS customers_groups (
329
		id INTEGER PRIMARY KEY AUTOINCREMENT,
330
		groupname TEXT NOT NULL)`); err != nil {
331
		return err
332
	}
333
	if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS customers (
334
		id INTEGER PRIMARY KEY AUTOINCREMENT,
335
		name CHAR(10) NOT NULL,
336
		updatetime TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
337
		age INT NULL,
338
		cust_group INT NOT NULL,
339
		FOREIGN KEY (cust_group) REFERENCES customers_groups (id) ON DELETE RESTRICT
340
		CONSTRAINT customers_un UNIQUE (name))`); err != nil {
341
		return err
342
	}
343
	return nil
344
}
345
346
func insertDataHelper(db *sql.DB) error {
347
348
	if _, err := db.Exec(`INSERT INTO customers_groups (groupname) VALUES('General');`); err != nil {
349
		return err
350
	}
351
352
	if statement, err := db.Prepare("INSERT INTO customers (name, updatetime, age, cust_group)VALUES(:1, :2, :3, :4)"); err != nil {
353
		return err
354
	} else {
355
		if _, err := statement.Exec("Juan", time.Now(), nil, 1); err != nil {
356
			return err
357
		}
358
		if _, err := statement.Exec("Pedro", time.Now(), nil, 1); err != nil {
359
			return err
360
		}
361
		if _, err := statement.Exec("Pablo", time.Now(), 99, 1); err != nil {
362
			return err
363
		}
364
	}
365
366
	return nil
367
}
368