{"id":47303312,"url":"https://github.com/cubrid-labs/cubrid-go","last_synced_at":"2026-04-01T17:21:06.515Z","repository":{"id":344778125,"uuid":"1180349249","full_name":"cubrid-labs/cubrid-go","owner":"cubrid-labs","description":"Pure-Go database/sql driver for CUBRID database","archived":false,"fork":false,"pushed_at":"2026-03-26T05:51:10.000Z","size":116,"stargazers_count":1,"open_issues_count":2,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T13:16:18.375Z","etag":null,"topics":["cubrid","cubrid-database","database","database-sql","driver","go-database-sql","golang","gorm","pure-go","sql"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/cubrid-labs/cubrid-go","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cubrid-labs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["cubrid-labs"]}},"created_at":"2026-03-13T00:30:38.000Z","updated_at":"2026-03-20T01:04:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cubrid-labs/cubrid-go","commit_stats":null,"previous_names":["cubrid-labs/cubrid-go"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/cubrid-labs/cubrid-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubrid-labs%2Fcubrid-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubrid-labs%2Fcubrid-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubrid-labs%2Fcubrid-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubrid-labs%2Fcubrid-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cubrid-labs","download_url":"https://codeload.github.com/cubrid-labs/cubrid-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubrid-labs%2Fcubrid-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cubrid","cubrid-database","database","database-sql","driver","go-database-sql","golang","gorm","pure-go","sql"],"created_at":"2026-03-17T06:27:31.659Z","updated_at":"2026-04-01T17:21:06.506Z","avatar_url":"https://github.com/cubrid-labs.png","language":"Go","funding_links":["https://github.com/sponsors/cubrid-labs"],"categories":[],"sub_categories":[],"readme":"# cubrid-go\n\n**Pure Go database driver for CUBRID** — `database/sql` interface + GORM dialector, no CGO required.\n\n\u003c!-- BADGES:START --\u003e\n[![Go Reference](https://pkg.go.dev/badge/github.com/cubrid-labs/cubrid-go.svg)](https://pkg.go.dev/github.com/cubrid-labs/cubrid-go)\n[![v0.2.1](https://img.shields.io/badge/version-v0.2.1-blue.svg)](https://github.com/cubrid-labs/cubrid-go/releases)\n[![Go 1.21+](https://img.shields.io/badge/go-1.21%2B-00ADD8.svg)](https://go.dev)\n[![CI](https://github.com/cubrid-labs/cubrid-go/actions/workflows/ci.yml/badge.svg)](https://github.com/cubrid-labs/cubrid-go/actions/workflows/ci.yml)\n[![license](https://img.shields.io/github/license/cubrid-labs/cubrid-go)](https://github.com/cubrid-labs/cubrid-go/blob/main/LICENSE)\n[![GitHub stars](https://img.shields.io/github/stars/cubrid-labs/cubrid-go)](https://github.com/cubrid-labs/cubrid-go)\n\u003c!-- BADGES:END --\u003e\n\n## Why cubrid-go?\n\n| | cubrid-go | CCI (C interface) |\n|:---|:---|:---|\n| **CGO Required** | No — pure Go | Yes |\n| **Cross-compilation** | `GOOS=linux GOARCH=arm64 go build` | Requires C toolchain |\n| **database/sql** | Native interface | Wrapper needed |\n| **GORM Support** | Built-in dialector | Not available |\n| **Connection Pool** | Go standard (`database/sql`) | Manual management |\n| **Deployment** | Single binary | Shared library dependency |\n\ncubrid-go speaks the CUBRID CAS protocol directly over TCP. No shared libraries, no CGO, no external dependencies — just `go get` and start coding.\n\n## Installation\n\n```bash\ngo get github.com/cubrid-labs/cubrid-go\n```\n\n**Requirements**: Go 1.21+\n\n## Quick Start\n\n### database/sql\n\n```go\npackage main\n\nimport (\n    \"database/sql\"\n    \"fmt\"\n    \"log\"\n\n    _ \"github.com/cubrid-labs/cubrid-go\"\n)\n\nfunc main() {\n    db, err := sql.Open(\"cubrid\", \"cubrid://dba:@localhost:33000/demodb\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer db.Close()\n\n    // Verify connection\n    if err := db.Ping(); err != nil {\n        log.Fatal(err)\n    }\n    fmt.Println(\"Connected to CUBRID!\")\n\n    // Query\n    rows, err := db.Query(\"SELECT name, nation_code FROM athlete WHERE nation_code = ?\", \"KOR\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer rows.Close()\n\n    for rows.Next() {\n        var name, nation string\n        rows.Scan(\u0026name, \u0026nation)\n        fmt.Printf(\"%s (%s)\\n\", name, nation)\n    }\n}\n```\n\n### GORM\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"log\"\n\n    \"gorm.io/gorm\"\n    cubrid \"github.com/cubrid-labs/cubrid-go/dialector\"\n)\n\ntype Athlete struct {\n    Code       int    `gorm:\"primaryKey;autoIncrement\"`\n    Name       string `gorm:\"size:40;not null\"`\n    NationCode string `gorm:\"size:3\"`\n    Gender     string `gorm:\"size:1\"`\n    Event      string `gorm:\"size:40\"`\n}\n\nfunc main() {\n    db, err := gorm.Open(cubrid.Open(\"cubrid://dba:@localhost:33000/demodb\"), \u0026gorm.Config{})\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Auto-migrate creates the table if it doesn't exist\n    db.AutoMigrate(\u0026Athlete{})\n\n    // Create\n    db.Create(\u0026Athlete{Name: \"Hong Gildong\", NationCode: \"KOR\", Gender: \"M\", Event: \"Marathon\"})\n\n    // Read\n    var athletes []Athlete\n    db.Where(\"nation_code = ?\", \"KOR\").Find(\u0026athletes)\n    for _, a := range athletes {\n        fmt.Printf(\"%s - %s\\n\", a.Name, a.Event)\n    }\n\n    // Update\n    db.Model(\u0026Athlete{}).Where(\"name = ?\", \"Hong Gildong\").Update(\"event\", \"Sprint\")\n\n    // Delete\n    db.Delete(\u0026Athlete{}, \"nation_code = ?\", \"ZZZ\")\n}\n```\n\n## DSN Format\n\n```\ncubrid://[user[:password]]@host[:port]/database[?autocommit=true\u0026timeout=30s]\n```\n\n| Parameter    | Default     | Description                         |\n|:-------------|:------------|:------------------------------------|\n| `host`       | `localhost` | CUBRID broker host                  |\n| `port`       | `33000`     | CUBRID broker port                  |\n| `database`   | *(required)* | Target database name               |\n| `user`       | `\"\"`        | Database user                       |\n| `password`   | `\"\"`        | Database password                   |\n| `autocommit` | `true`      | Enable/disable auto-commit          |\n| `timeout`    | `30s`       | Connection timeout ([Go duration](https://pkg.go.dev/time#ParseDuration)) |\n\n**Examples**:\n\n```go\n// Local development\n\"cubrid://dba:@localhost:33000/demodb\"\n\n// Remote with credentials\n\"cubrid://admin:secret@db.example.com:33000/production\"\n\n// Manual transaction mode\n\"cubrid://dba:@localhost:33000/demodb?autocommit=false\"\n\n// Custom timeout\n\"cubrid://dba:@localhost:33000/demodb?timeout=60s\"\n```\n\n## Connection Pooling\n\n`cubrid-go` uses Go's standard `database/sql` pool, so the usual pool tuning APIs work as expected.\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"database/sql\"\n    \"log\"\n    \"time\"\n\n    _ \"github.com/cubrid-labs/cubrid-go\"\n)\n\nfunc main() {\n    db, err := sql.Open(\"cubrid\", \"cubrid://dba:@localhost:33000/demodb\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    defer db.Close()\n\n    // Configure the shared connection pool.\n    db.SetMaxOpenConns(25)\n    db.SetMaxIdleConns(5)\n    db.SetConnMaxLifetime(5 * time.Minute)\n    db.SetConnMaxIdleTime(1 * time.Minute)\n\n    // Verify that the broker is reachable before serving traffic.\n    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)\n    defer cancel()\n\n    if err := db.PingContext(ctx); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n### Pool settings\n\n- `SetMaxOpenConns(25)`: caps the total number of open connections. Start with a conservative number and scale up only if your broker and workload need it.\n- `SetMaxIdleConns(5)`: keeps a small number of warm idle connections ready for bursts without holding on to the full pool.\n- `SetConnMaxLifetime(5 * time.Minute)`: rotates long-lived connections so stale sessions do not accumulate forever.\n- `SetConnMaxIdleTime(1 * time.Minute)`: closes connections that have been idle for too long, which is useful for spiky traffic.\n\n### Recommended starting point\n\nFor a typical web service, a good baseline is:\n\n- `MaxOpenConns`: `10` to `25`\n- `MaxIdleConns`: `2` to `5`\n- `ConnMaxLifetime`: `5m` to `30m`\n- `ConnMaxIdleTime`: `1m` to `5m`\n\nMeasure under production-like load and adjust from there. If requests begin queueing on the Go side, raise `MaxOpenConns` carefully. If the database is saturated, lower it.\n\n### CUBRID-specific notes\n\n- The pool limit should stay below the available CUBRID broker worker capacity. Setting `MaxOpenConns` higher than the broker can actually serve only shifts contention downstream.\n- `PingContext()` is a good readiness or startup check because it fails fast when the broker is unavailable or the DSN is invalid.\n- If your deployment has multiple application instances, size the pool per instance, not just per service. For example, `25` open connections across `4` replicas can become `100` broker sessions.\n\n## Supported Features\n\n| Feature | Status | Notes |\n|:--------|:-------|:------|\n| Pure TCP (no shared library) | ✅ | No CGO, no external deps |\n| `database/sql` driver | ✅ | Full interface |\n| Parameterized queries (`?`) | ✅ | Client-side interpolation |\n| Transactions (`Begin/Commit/Rollback`) | ✅ | |\n| GORM dialector | ✅ | Models, migrations, CRUD |\n| GORM AutoMigrate | ✅ | Create tables, add columns |\n| Server-side cursor / lazy fetch | ✅ | Batches of 100 rows |\n| Result streaming (FETCH) | ✅ | Memory-efficient |\n| Last insert ID | ✅ | Via `SELECT LAST_INSERT_ID()` |\n| Connection pool | ✅ | Go standard `database/sql` |\n| Connection health check (Ping) | ✅ | Via `GET_DB_VERSION` |\n| LOB (BLOB/CLOB) | ⚠️ | Raw bytes only |\n| Timezone-aware types | ⚠️ | UTC only |\n| ON CONFLICT / UPSERT | ❌ | Use raw SQL workaround |\n\n## Type Mapping\n\n### Go → CUBRID (Parameters)\n\n| Go Type | CUBRID Literal | Example |\n|:--------|:---------------|:--------|\n| `nil` | `NULL` | |\n| `bool` | `0` / `1` | CUBRID has no BOOLEAN |\n| `int64` | Integer | `42` |\n| `float64` | Float | `3.14` |\n| `string` | `'escaped'` | Quotes doubled |\n| `[]byte` | `X'cafe'` | Hex-encoded |\n| `time.Time` | `DATETIME'...'` | Millisecond precision |\n\n### CUBRID → Go (Results)\n\n| CUBRID Type | Go Type |\n|:------------|:--------|\n| `SMALLINT`, `INTEGER`, `BIGINT` | `int64` |\n| `FLOAT`, `DOUBLE`, `MONETARY` | `float64` |\n| `NUMERIC` | `string` |\n| `CHAR`, `VARCHAR`, `STRING` | `string` |\n| `DATE`, `TIME`, `DATETIME`, `TIMESTAMP` | `time.Time` (UTC) |\n| `BIT`, `BIT VARYING`, `BLOB`, `CLOB` | `[]byte` |\n| `SET`, `MULTISET`, `SEQUENCE` | `string` |\n\n## GORM Type Mapping\n\n| GORM Field Type | CUBRID SQL Type |\n|:----------------|:----------------|\n| `Bool` | `SMALLINT` |\n| `Int` (≤16 bits) | `SMALLINT` |\n| `Int` (≤32 bits) | `INTEGER` |\n| `Int` (\u003e32 bits) | `BIGINT` |\n| `Float` (≤32 bits) | `FLOAT` |\n| `Float` (\u003e32 bits) | `DOUBLE` |\n| `String` | `VARCHAR(n)` (default 256) |\n| `String` (very large) | `STRING` |\n| `Time` | `DATETIME` |\n| `Bytes` | `BLOB` |\n| Auto-increment (≤32) | `INTEGER AUTO_INCREMENT` |\n| Auto-increment (\u003e32) | `BIGINT AUTO_INCREMENT` |\n\n## Error Types\n\n```go\nimport \"github.com/cubrid-labs/cubrid-go\"\n\n// Base error\nvar cubridErr *cubrid.CubridError\n\n// Constraint violation (unique, foreign key)\nvar integrityErr *cubrid.IntegrityError\n\n// SQL syntax error, missing table/column\nvar progErr *cubrid.ProgrammingError\n\n// Network/connection failure\nvar opErr *cubrid.OperationalError\n\n// Use errors.As for type checking\nif errors.As(err, \u0026integrityErr) {\n    fmt.Printf(\"Constraint violation: code=%d msg=%s\\n\", integrityErr.Code, integrityErr.Message)\n}\n```\n\n## Architecture\n\n```mermaid\nflowchart TD\n    A[Application] --\u003e B[cubrid-go database/sql driver]\n    B --\u003e C[CAS Protocol net.Conn]\n    C --\u003e D[CUBRID Server]\n```\n\n```mermaid\nflowchart TD\n    R[cubrid-go/] --\u003e C1[constants.go\\nCAS protocol constants function codes, data types]\n    R --\u003e C2[packet.go\\nPacketWriter / PacketReader big-endian binary codec]\n    R --\u003e C3[protocol.go\\nHigh-level packet builders and parsers]\n    R --\u003e C4[errors.go\\nCubridError, IntegrityError, ProgrammingError, OperationalError]\n    R --\u003e C5[types.go\\nFormatValue Go to CUBRID type conversion]\n    R --\u003e C6[conn.go\\nTCP connection + two-step broker handshake]\n    R --\u003e C7[stmt.go\\ndatabase/sql Stmt PrepareAndExecute FC=41]\n    R --\u003e C8[rows.go\\ndatabase/sql Rows lazy server-side cursor FC=8]\n    R --\u003e C9[tx.go\\ndatabase/sql Tx COMMIT / ROLLBACK FC=1]\n    R --\u003e C10[driver.go\\nDriver registration + DSN parser]\n    R --\u003e D[dialector/]\n    D --\u003e D1[cubrid.go\\nGORM Dialector + Migrator]\n```\n\n## Protocol Notes\n\ncubrid-go speaks the CUBRID CAS (Client Application Server) protocol directly over TCP. The two-step connection sequence is:\n\n1. **Broker handshake** — connect to `host:port`, send a 10-byte magic string, receive a redirected CAS port.\n2. **Open database** — connect to the CAS port, send credentials (628 bytes), receive session info.\n\nAll subsequent requests use the `PREPARE_AND_EXECUTE` (function code 41) combined packet, and large result sets are streamed back via `FETCH` (function code 8).\n\n## Documentation\n\n| Document | Description |\n|:---------|:------------|\n| [API Reference](docs/API_REFERENCE.md) | Complete `database/sql` driver API, DSN format, type mapping, error types, protocol details |\n| [GORM Guide](docs/GORM.md) | GORM dialector setup, models, migrations, CRUD, transactions, querying, schema inspection |\n| [Troubleshooting](docs/TROUBLESHOOTING.md) | Connection, query, transaction, GORM, type, and performance issues with solutions |\n\n## FAQ\n\n### How do I connect to CUBRID with Go?\n\n```go\nimport (\n    \"database/sql\"\n    _ \"github.com/cubrid-labs/cubrid-go\"\n)\ndb, err := sql.Open(\"cubrid\", \"cubrid://dba:@localhost:33000/demodb\")\n```\n\n### How do I use CUBRID with GORM?\n\n```go\nimport (\n    \"gorm.io/gorm\"\n    cubrid \"github.com/cubrid-labs/cubrid-go/dialector\"\n)\ndb, err := gorm.Open(cubrid.Open(\"cubrid://dba:@localhost:33000/demodb\"), \u0026gorm.Config{})\n```\n\n### Does cubrid-go require CGO?\n\nNo. cubrid-go is a pure Go implementation that speaks the CUBRID CAS protocol directly over TCP. No shared libraries or CGO needed.\n\n### What Go version is required?\n\nGo 1.21 or later.\n\n### Does cubrid-go support connection pooling?\n\nYes. See the [Connection Pooling](#connection-pooling) section for a production-oriented example with `PingContext()` and recommended starting values.\n\n### Does cubrid-go support transactions?\n\nYes. Use `db.Begin()` to start a transaction, then `tx.Commit()` or `tx.Rollback()`.\n\n### Does GORM AutoMigrate work with CUBRID?\n\nYes. The GORM dialector supports `AutoMigrate` for creating and updating table schemas.\n\n## Benchmark\n\n**Environment**: Intel Core i5-9400F @ 2.90GHz · Linux x86_64 · CUBRID 11.2 · MySQL 8.0 · Docker localhost\n\n**Test Parameters**: 1000 rows × 5 rounds\n\n| Operation | cubrid-go (CUBRID) | go-sql-driver (MySQL) | Ratio |\n|-----------|-------------------|----------------------|-------|\n| insert_sequential | 0.98s | 1.02s | 1.0× |\n| select_by_pk | 1.58s | 1.14s | 1.4× |\n| select_full_scan | 1.02s | 1.11s | 0.9× |\n| update_indexed | 1.07s | 1.11s | 1.0× |\n| delete_sequential | 1.14s | 1.06s | 1.1× |\n\n**Note**: cubrid-go performs on par with go-sql-driver/mysql — nearly identical throughput across all operations.\n\nFull benchmark suite: [cubrid-benchmark](https://github.com/cubrid-labs/cubrid-benchmark)\n\n\n## Ecosystem\n\n| Package | Description | Language |\n|:--------|:------------|:---------|\n| [cubrid-go](https://github.com/cubrid-labs/cubrid-go) | database/sql driver + GORM dialector | Go |\n| [gorm-cubrid](https://github.com/cubrid-labs/gorm-cubrid) | GORM dialect for CUBRID | Go |\n| [pycubrid](https://github.com/cubrid-labs/pycubrid) | PEP 249 DB-API 2.0 driver | Python |\n| [sqlalchemy-cubrid](https://github.com/cubrid-labs/sqlalchemy-cubrid) | SQLAlchemy 2.0 dialect | Python |\n| [cubrid-client](https://github.com/cubrid-labs/cubrid-client) | Modern TypeScript client | TypeScript |\n| [drizzle-cubrid](https://github.com/cubrid-labs/drizzle-cubrid) | Drizzle ORM dialect | TypeScript |\n| [cubrid-rs](https://github.com/cubrid-labs/cubrid-rs) | Native Rust database driver for CUBRID (sync + async, pure Rust) | Rust |\n| [sea-orm-cubrid](https://github.com/cubrid-labs/sea-orm-cubrid) | SeaORM backend for CUBRID | Rust |\n| [cubrid-cookbook](https://github.com/cubrid-labs/cubrid-cookbook) | Working examples for all platforms | Multi |\n\n## Roadmap\n\nSee [`ROADMAP.md`](ROADMAP.md) for this project's direction and next milestones.\n\nFor the ecosystem-wide view, see the [CUBRID Labs Ecosystem Roadmap](https://github.com/cubrid-labs/.github/blob/main/ROADMAP.md) and [Project Board](https://github.com/orgs/cubrid-labs/projects/2).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubrid-labs%2Fcubrid-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcubrid-labs%2Fcubrid-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubrid-labs%2Fcubrid-go/lists"}