@@ -341,28 +341,267 @@ func TestDB_IsValid(t *testing.T) {
341
341
name : "simple valid select query is handled" ,
342
342
setupMock : func (mock pgxmock.PgxPoolIface ) {
343
343
rows := pgxmock .NewRowsWithColumnDefinition (
344
- pgconn.FieldDescription {Name : "id" },
345
- pgconn.FieldDescription {Name : "name" },
346
- ).AddRow (1 , "John Doe" )
347
- mock .ExpectQuery ("EXPLAIN SELECT 1;" ).WillReturnRows (rows )
344
+ pgconn.FieldDescription {Name : "result" },
345
+ ).AddRow ("DO" )
346
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
347
+ SELECT 1
348
+ END; \$TEST\$;`
349
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
348
350
},
349
351
query : query.Query {
350
352
Query : "SELECT 1" ,
351
353
},
352
354
want : true ,
353
355
},
354
356
{
355
- name : "invalid query is properly handled" ,
357
+ name : "complex valid query with multiple statements" ,
358
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
359
+ rows := pgxmock .NewRowsWithColumnDefinition (
360
+ pgconn.FieldDescription {Name : "result" },
361
+ ).AddRow ("DO" )
362
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
363
+ SELECT id, name FROM users WHERE active = true
364
+ END; \$TEST\$;`
365
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
366
+ },
367
+ query : query.Query {
368
+ Query : "SELECT id, name FROM users WHERE active = true" ,
369
+ },
370
+ want : true ,
371
+ },
372
+ {
373
+ name : "valid INSERT query" ,
374
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
375
+ rows := pgxmock .NewRowsWithColumnDefinition (
376
+ pgconn.FieldDescription {Name : "result" },
377
+ ).AddRow ("DO" )
378
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
379
+ INSERT INTO users \(name, email\) VALUES \('John', 'john@example\.com'\)
380
+ END; \$TEST\$;`
381
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
382
+ },
383
+ query : query.Query {
384
+ Query :
"INSERT INTO users (name, email) VALUES ('John', '[email protected] ')" ,
385
+ },
386
+ want : true ,
387
+ },
388
+ {
389
+ name : "valid UPDATE query" ,
390
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
391
+ rows := pgxmock .NewRowsWithColumnDefinition (
392
+ pgconn.FieldDescription {Name : "result" },
393
+ ).AddRow ("DO" )
394
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
395
+ UPDATE users SET active = false WHERE last_login < NOW\(\) - INTERVAL '1 year'
396
+ END; \$TEST\$;`
397
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
398
+ },
399
+ query : query.Query {
400
+ Query : "UPDATE users SET active = false WHERE last_login < NOW() - INTERVAL '1 year'" ,
401
+ },
402
+ want : true ,
403
+ },
404
+ {
405
+ name : "valid DELETE query" ,
406
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
407
+ rows := pgxmock .NewRowsWithColumnDefinition (
408
+ pgconn.FieldDescription {Name : "result" },
409
+ ).AddRow ("DO" )
410
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
411
+ DELETE FROM logs WHERE created_at < NOW\(\) - INTERVAL '30 days'
412
+ END; \$TEST\$;`
413
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
414
+ },
415
+ query : query.Query {
416
+ Query : "DELETE FROM logs WHERE created_at < NOW() - INTERVAL '30 days'" ,
417
+ },
418
+ want : true ,
419
+ },
420
+ {
421
+ name : "invalid query with syntax error" ,
356
422
setupMock : func (mock pgxmock.PgxPoolIface ) {
357
- mock .ExpectQuery (`EXPLAIN some broken query;` ).
358
- WillReturnError (errors .New ("some actual error" ))
423
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
424
+ SELECT \* FORM users
425
+ END; \$TEST\$;`
426
+ mock .ExpectQuery (expectedQuery ).
427
+ WillReturnError (errors .New ("syntax error at or near \" FORM\" " ))
428
+ },
429
+ query : query.Query {
430
+ Query : "SELECT * FORM users" ,
431
+ },
432
+ want : false ,
433
+ wantErr : true ,
434
+ errorMessage : "syntax error at or near \" FORM\" " ,
435
+ },
436
+ {
437
+ name : "invalid query with missing table" ,
438
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
439
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
440
+ SELECT \* FROM non_existent_table
441
+ END; \$TEST\$;`
442
+ mock .ExpectQuery (expectedQuery ).
443
+ WillReturnError (errors .New ("relation \" non_existent_table\" does not exist" ))
444
+ },
445
+ query : query.Query {
446
+ Query : "SELECT * FROM non_existent_table" ,
447
+ },
448
+ want : false ,
449
+ wantErr : true ,
450
+ errorMessage : "relation \" non_existent_table\" does not exist" ,
451
+ },
452
+ {
453
+ name : "invalid query with wrong column reference" ,
454
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
455
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
456
+ SELECT invalid_column FROM users
457
+ END; \$TEST\$;`
458
+ mock .ExpectQuery (expectedQuery ).
459
+ WillReturnError (errors .New ("column \" invalid_column\" does not exist" ))
460
+ },
461
+ query : query.Query {
462
+ Query : "SELECT invalid_column FROM users" ,
463
+ },
464
+ want : false ,
465
+ wantErr : true ,
466
+ errorMessage : "column \" invalid_column\" does not exist" ,
467
+ },
468
+ {
469
+ name : "query with CTE (WITH clause)" ,
470
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
471
+ rows := pgxmock .NewRowsWithColumnDefinition (
472
+ pgconn.FieldDescription {Name : "result" },
473
+ ).AddRow ("DO" )
474
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
475
+ WITH active_users AS \(SELECT \* FROM users WHERE active = true\) SELECT \* FROM active_users
476
+ END; \$TEST\$;`
477
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
478
+ },
479
+ query : query.Query {
480
+ Query : "WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users" ,
481
+ },
482
+ want : true ,
483
+ },
484
+ {
485
+ name : "query with JOIN" ,
486
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
487
+ rows := pgxmock .NewRowsWithColumnDefinition (
488
+ pgconn.FieldDescription {Name : "result" },
489
+ ).AddRow ("DO" )
490
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
491
+ SELECT u\.name, p\.title FROM users u JOIN posts p ON u\.id = p\.user_id
492
+ END; \$TEST\$;`
493
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
494
+ },
495
+ query : query.Query {
496
+ Query : "SELECT u.name, p.title FROM users u JOIN posts p ON u.id = p.user_id" ,
497
+ },
498
+ want : true ,
499
+ },
500
+ {
501
+ name : "invalid query with broken SQL" ,
502
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
503
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
504
+ some broken query
505
+ END; \$TEST\$;`
506
+ mock .ExpectQuery (expectedQuery ).
507
+ WillReturnError (errors .New ("syntax error" ))
359
508
},
360
509
query : query.Query {
361
510
Query : "some broken query" ,
362
511
},
363
512
want : false ,
364
513
wantErr : true ,
365
- errorMessage : "some actual error" ,
514
+ errorMessage : "syntax error" ,
515
+ },
516
+ {
517
+ name : "query with multiline formatting" ,
518
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
519
+ rows := pgxmock .NewRowsWithColumnDefinition (
520
+ pgconn.FieldDescription {Name : "result" },
521
+ ).AddRow ("DO" )
522
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
523
+ SELECT
524
+ id,
525
+ name,
526
+ email
527
+ FROM users
528
+ WHERE active = true
529
+ END; \$TEST\$;`
530
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
531
+ },
532
+ query : query.Query {
533
+ Query : `SELECT
534
+ id,
535
+ name,
536
+ email
537
+ FROM users
538
+ WHERE active = true` ,
539
+ },
540
+ want : true ,
541
+ },
542
+ {
543
+ name : "CREATE TABLE query validation" ,
544
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
545
+ rows := pgxmock .NewRowsWithColumnDefinition (
546
+ pgconn.FieldDescription {Name : "result" },
547
+ ).AddRow ("DO" )
548
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
549
+ CREATE TABLE test_table \(id SERIAL PRIMARY KEY, name VARCHAR\(100\)\)
550
+ END; \$TEST\$;`
551
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
552
+ },
553
+ query : query.Query {
554
+ Query : "CREATE TABLE test_table (id SERIAL PRIMARY KEY, name VARCHAR(100))" ,
555
+ },
556
+ want : true ,
557
+ },
558
+ {
559
+ name : "ALTER TABLE query validation" ,
560
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
561
+ rows := pgxmock .NewRowsWithColumnDefinition (
562
+ pgconn.FieldDescription {Name : "result" },
563
+ ).AddRow ("DO" )
564
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
565
+ ALTER TABLE users ADD COLUMN age INTEGER
566
+ END; \$TEST\$;`
567
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
568
+ },
569
+ query : query.Query {
570
+ Query : "ALTER TABLE users ADD COLUMN age INTEGER" ,
571
+ },
572
+ want : true ,
573
+ },
574
+ {
575
+ name : "DROP TABLE query validation" ,
576
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
577
+ rows := pgxmock .NewRowsWithColumnDefinition (
578
+ pgconn.FieldDescription {Name : "result" },
579
+ ).AddRow ("DO" )
580
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
581
+ DROP TABLE IF EXISTS temp_table
582
+ END; \$TEST\$;`
583
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
584
+ },
585
+ query : query.Query {
586
+ Query : "DROP TABLE IF EXISTS temp_table" ,
587
+ },
588
+ want : true ,
589
+ },
590
+ {
591
+ name : "query with special characters in strings" ,
592
+ setupMock : func (mock pgxmock.PgxPoolIface ) {
593
+ rows := pgxmock .NewRowsWithColumnDefinition (
594
+ pgconn.FieldDescription {Name : "result" },
595
+ ).AddRow ("DO" )
596
+ expectedQuery := `DO \$TEST\$ BEGIN RETURN;
597
+ SELECT \* FROM users WHERE name = 'O''Brien' AND email LIKE '%@example\.com'
598
+ END; \$TEST\$;`
599
+ mock .ExpectQuery (expectedQuery ).WillReturnRows (rows )
600
+ },
601
+ query : query.Query {
602
+ Query : "SELECT * FROM users WHERE name = 'O''Brien' AND email LIKE '%@example.com'" ,
603
+ },
604
+ want : true ,
366
605
},
367
606
}
368
607
for _ , tt := range tests {
0 commit comments