Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handle Gorm query style #77

Merged
merged 11 commits into from
Jul 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ install: ## install binaries
test: ## test
go test -v ./...

bench:
go test -bench=. -count 6 | tee newbench.txt
benchstat bench.txt newbench.txt | tee benchstat.txt

format:
mdformat README.md
103 changes: 96 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Bottom line : One DataSourceName per test and you have full test isolation in no
go get github.com/proullon/ramsql
```

## Usage
## Usage

Let's say you want to test the function LoadUserAddresses :

Expand Down Expand Up @@ -48,6 +48,7 @@ func LoadUserAddresses(db *sql.DB, userID int64) ([]string, error) {
}

```

Use RamSQL to test it in a disposable isolated in-memory SQL engine :

```go
Expand Down Expand Up @@ -115,6 +116,7 @@ Let's say you have a SQL describing your application structure:
CREATE TABLE IF NOT EXISTS address (id BIGSERIAL PRIMARY KEY, street TEXT, street_number INT);
CREATE TABLE IF NOT EXISTS user_addresses (address_id INT, user_id INT);
```

You may want to test its validity:

```console
Expand All @@ -128,6 +130,49 @@ $ echo $?

## Features

Find bellow all objectives for `v1.0.0`

| Name | Category | Parsing | Implementation |
| -------------- | ------------- | ------------------------ | ------------------------ |
| Table | SQL | :heavy_check_mark: | :heavy_check_mark: |
| Schema | SQL | :heavy_check_mark: | :heavy_check_mark: |
| CREATE | SQL | :heavy_check_mark: | :heavy_check_mark: |
| PRIMARY_KEY | SQL | :heavy_check_mark: | :heavy_multiplication_x: |
| DEFAULT | SQL | :heavy_check_mark: | :heavy_check_mark: |
| INSERT | SQL | :heavy_check_mark: | :heavy_check_mark: |
| UNIQUE | SQL | :heavy_check_mark: | :heavy_check_mark: |
| FOREIGN KEY | SQL | :heavy_multiplication_x: | :heavy_multiplication_x: |
| SELECT | SQL | :heavy_check_mark: | :heavy_check_mark: |
| backtick | SQL | :heavy_check_mark: | :heavy_check_mark: |
| quote | SQL | :heavy_check_mark: | :heavy_check_mark: |
| double quote | SQL | :heavy_check_mark: | :heavy_check_mark: |
| COUNT | SQL | :heavy_check_mark: | :heavy_check_mark: |
| MAX | SQL | :heavy_check_mark: | :heavy_check_mark: |
| ORDER BY | SQL | :heavy_check_mark: | single column |
| UPDATE | SQL | :heavy_check_mark: | :heavy_check_mark: |
| DELETE | SQL | :heavy_check_mark: | :heavy_check_mark: |
| DROP | SQL | :heavy_check_mark: | :heavy_check_mark: |
| INNER JOIN | SQL | :heavy_check_mark: | :heavy_check_mark: |
| OUTER JOIN | SQL | :heavy_check_mark: | :heavy_multiplication_x: |
| timestamp | SQL | :heavy_check_mark: | :heavy_check_mark: |
| now() | SQL | :heavy_check_mark: | :heavy_check_mark: |
| OFFSET | SQL | :heavy_check_mark: | :heavy_check_mark: |
| Transactions | SQL | :heavy_check_mark: | partial |
| BEGIN | SQL | :heavy_multiplication_x: | :heavy_multiplication_x: |
| COMMIT | SQL | :heavy_multiplication_x: | :heavy_multiplication_x: |
| Index | SQL | :heavy_check_mark: | :heavy_multiplication_x: |
| Hash index | SQL | :heavy_check_mark: | :heavy_multiplication_x: |
| B-Tree index | SQL | :heavy_check_mark: | :heavy_multiplication_x: |
| JSON | SQL | :heavy_multiplication_x: | :heavy_multiplication_x: |
| CLI | Testing | :heavy_check_mark: | :heavy_check_mark: |
| Breakpoint | Testing | :heavy_multiplication_x: | :heavy_multiplication_x: |
| Query history | Testing | :heavy_multiplication_x: | :heavy_multiplication_x: |
| Size limit | Testing | :heavy_multiplication_x: | :heavy_multiplication_x: |
| Autogeneration | Testing | :heavy_multiplication_x: | :heavy_multiplication_x: |
| TTL | Caching | :heavy_multiplication_x: | :heavy_multiplication_x: |
| LFRU | Caching | :heavy_multiplication_x: | :heavy_multiplication_x: |
| Gorm | Compatibility | :heavy_multiplication_x: | :heavy_multiplication_x: |

### Unit testing

- Full isolation between tests
Expand All @@ -136,24 +181,68 @@ $ echo $?

### SQL parsing

- Databse schema validation
- Database schema validation
- ALTER file validation

### Stress testing

- File system full error with configurable maximum database size
- Random configurable slow queries
- Random deconnection
- Random connection error

## Compatibility

### GORM

If you intend to use ramsql with the GORM ORM, you should use the GORM Postgres driver. A working example would be:

```go
sqlDB, err := sql.Open("ramsql", "Test")
...
import (
"database/sql"
"testing"

"gorm.io/driver/postgres"
"gorm.io/gorm"
)

type Product struct {
gorm.Model
Code string
Price uint
TestBigint uint64 `gorm:"test_bigint;type:BIGINT UNSIGNED AUTO_INCREMENT"`
}

// From https://gorm.io/docs/connecting_to_the_database.html
// and https://gorm.io/docs/
func main() {
ramdb, err := sql.Open("ramsql", "TestGormQuickStart")

db, err := gorm.Open(postgres.New(postgres.Config{
Conn: sqlDB,
}), &gorm.Config{})
Conn: ramdb,
}),
&gorm.Config{})

// Migrate the schema
err = db.AutoMigrate(&Product{})

// Create
err = db.Create(&Product{Code: "D42", Price: 100}).Error

// Read
var product Product
err = db.First(&product, 1).Error // find product with integer primary key
err = db.First(&product, "code = ?", "D42").Error // find product with code D42
err = db.First(&product, "Code = ?", "D42").Error // find product with code D42

// Update - update product's price to 200
err = db.Model(&product).Update("Price", 200).Error
// Update - update multiple fields
err = db.Model(&product).Updates(Product{Price: 200, Code: "F42"}).Error // non-zero fields
err = db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"}).Error

// Delete - delete product
err = db.Delete(&product, 1).Error

_ = err
}
```
54 changes: 54 additions & 0 deletions bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
goos: linux
goarch: amd64
pkg: github.com/proullon/ramsql
cpu: Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
BenchmarkRamSQLSelect-8 3766 297732 ns/op
BenchmarkRamSQLSelect-8 4114 286406 ns/op
BenchmarkRamSQLSelect-8 3974 287603 ns/op
BenchmarkRamSQLSelect-8 3874 286818 ns/op
BenchmarkRamSQLSelect-8 4036 286082 ns/op
BenchmarkRamSQLSelect-8 3924 285952 ns/op
BenchmarkSQLiteSelect-8 110434 10706 ns/op
BenchmarkSQLiteSelect-8 112434 10805 ns/op
BenchmarkSQLiteSelect-8 99657 11055 ns/op
BenchmarkSQLiteSelect-8 111702 10689 ns/op
BenchmarkSQLiteSelect-8 111669 10756 ns/op
BenchmarkSQLiteSelect-8 111285 10638 ns/op
BenchmarkRamSQLSelect10K-8 160 7384466 ns/op
BenchmarkRamSQLSelect10K-8 162 7938318 ns/op
BenchmarkRamSQLSelect10K-8 160 7456492 ns/op
BenchmarkRamSQLSelect10K-8 159 7502256 ns/op
BenchmarkRamSQLSelect10K-8 164 7540972 ns/op
BenchmarkRamSQLSelect10K-8 144 7451605 ns/op
BenchmarkSQLiteSelect10K-8 109460 10979 ns/op
BenchmarkSQLiteSelect10K-8 105711 11033 ns/op
BenchmarkSQLiteSelect10K-8 104372 11035 ns/op
BenchmarkSQLiteSelect10K-8 107712 11063 ns/op
BenchmarkSQLiteSelect10K-8 107395 11060 ns/op
BenchmarkSQLiteSelect10K-8 108666 11116 ns/op
BenchmarkRamSQLInsert10-8 4424 268468 ns/op
BenchmarkRamSQLInsert10-8 4477 298751 ns/op
BenchmarkRamSQLInsert10-8 4242 280029 ns/op
BenchmarkRamSQLInsert10-8 3828 283994 ns/op
BenchmarkRamSQLInsert10-8 4328 283040 ns/op
BenchmarkRamSQLInsert10-8 4436 276176 ns/op
BenchmarkSQLiteInsert10-8 3459 332308 ns/op
BenchmarkSQLiteInsert10-8 3721 328695 ns/op
BenchmarkSQLiteInsert10-8 3709 330266 ns/op
BenchmarkSQLiteInsert10-8 3670 343643 ns/op
BenchmarkSQLiteInsert10-8 3680 320361 ns/op
BenchmarkSQLiteInsert10-8 3819 325789 ns/op
BenchmarkRamSQLSetup-8 1430150 832.9 ns/op
BenchmarkRamSQLSetup-8 1436343 835.1 ns/op
BenchmarkRamSQLSetup-8 1439770 833.9 ns/op
BenchmarkRamSQLSetup-8 1331280 806.1 ns/op
BenchmarkRamSQLSetup-8 1485778 807.0 ns/op
BenchmarkRamSQLSetup-8 1486251 806.3 ns/op
BenchmarkSQLiteSetup-8 1477396 810.5 ns/op
BenchmarkSQLiteSetup-8 1464448 809.5 ns/op
BenchmarkSQLiteSetup-8 1380595 814.2 ns/op
BenchmarkSQLiteSetup-8 1482067 811.0 ns/op
BenchmarkSQLiteSetup-8 1481173 813.0 ns/op
BenchmarkSQLiteSetup-8 1480530 811.3 ns/op
PASS
ok github.com/proullon/ramsql 87.537s
Loading