oceanbase

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

README

obconnector-go

中文文档

Clean-room OceanBase driver experiments for Go's database/sql.

The first milestone is a pure-Go PoC that can connect to an OceanBase Oracle tenant and run:

select 1 from dual

This repository intentionally does not depend on OBCI, Oracle Instant Client, LibOBClient, cgo, or dynamic OceanBase client libraries.

Current State

  • Registers database/sql driver names oceanbase and oboracle.
  • Implements a minimal MySQL-compatible wire path with OceanBase Oracle tenant handshake extensions.
  • Supports mysql_native_password, COM_QUERY, streaming text rows, server errors, basic transactions, Prepare compatibility, client-side ? parameter interpolation, connection-pool lifecycle hooks, and basic column type metadata.
  • Provides cmd/obping for connection experiments and regression testing.
  • Records protocol observations and open questions in docs/protocol-notes.md.

The implementation is not production-ready. It is designed to support packet captures and connection experiments without copying LGPL/MariaDB/OBConnector-C source code.

obping — Connection & Regression Testing Tool

cmd/obping is a CLI tool for testing connections and running integration tests against OceanBase tenants (both Oracle and MySQL mode).

Quick Start
go run ./cmd/obping \
  -host 127.0.0.1 \
  -port 2881 \
  -user '<user@tenant#cluster>' \
  -password '<password>' \
  -trace

Or pass a DSN directly:

go run ./cmd/obping \
  -dsn 'oceanbase://<user>:<password>@<host>:<port>/?timeout=5s'
All Flags
Flag Default Description
-dsn "" Full DSN (overrides individual flags)
-host 127.0.0.1 OceanBase host or OBProxy host
-port 2881 OceanBase port or OBProxy port
-user "" OceanBase user, often user@tenant#cluster
-password "" OceanBase password
-database "" Database/schema name
-timeout 10s Connect and query timeout
-tls false Enable TLS encryption
-tls-ca "" Path to CA certificate file for TLS
-oracle-mode false Force Oracle mode
-mysql-mode false Force MySQL mode
-trace false Print handshake and query trace to stderr
-preset "" Client identity preset (default, oboracle, obclient, ...)
-ob20 false Enable OB 2.0 protocol encapsulation
-probe-presets false Try all presets until one succeeds
-query "select 1 from dual" Query to execute
-max-rows 20 Maximum rows to print
-attr Connection attribute key=value (repeatable)
-init SQL to run after auth (repeatable)
-cap-add "" Capability bits to force on (0x200000)
-cap-drop "" Capability bits to force off (0x100000)
-collation "" Handshake collation ID (45)
-exec-table "" Table name for exec-test
Test Flags
Flag Description
-tx-test Basic BEGIN / COMMIT / ROLLBACK transaction test
-exec-test DDL/DML smoke test (create, insert, update, delete)
-param-test Parameterized ? query/exec test
-pool-test database/sql connection pool lifecycle test
-bulk-test BulkInsert helper test
-full-test Comprehensive integration test (all of the above combined)
DSN

URL-style DSN (recommended):

oceanbase://<user>:<password>@<host>:<port>/<database>?<params>

Opaque DSN (legacy):

oceanbase:<user>:<password>@<host>:<port>/<database>?<params>
DSN Parameters
Parameter Values Description
timeout Duration (5s, 10s) Connection and read/write timeout
trace true/false Print handshake and query details
tls true/skip-verify/false Enable TLS
tls.ca File path Path to CA certificate for TLS
oracleMode true/false/auto Force Oracle/MySQL mode or auto-detect
ob20 true/false Enable OB 2.0 protocol encapsulation
preset default/oboracle/obclient/... Client identity preset
collation uint8 Handshake collation byte
cap.add uint32 Force capability bits on
cap.drop uint32 Force capability bits off
attr.<key> String Connection attribute
init SQL SQL to run after authentication (repeatable)
Custom Query
go run ./cmd/obping \
  -dsn 'oceanbase://<user>:<password>@<host>:<port>/?timeout=5s' \
  -query 'select 1 as one from dual' \
  -max-rows 20
DDL/DML Test
go run ./cmd/obping \
  -dsn 'oceanbase://<user>:<password>@<host>:<port>/?timeout=5s' \
  -exec-test
Parameterized Query Test
go run ./cmd/obping \
  -dsn 'oceanbase://<user>:<password>@<host>:<port>/?timeout=5s' \
  -param-test
Connection Pool Test
go run ./cmd/obping \
  -dsn 'oceanbase://<user>:<password>@<host>:<port>/?timeout=5s' \
  -pool-test \
  -trace
Oracle Tenant — Full Integration Test
go run ./cmd/obping \
  -host <host> \
  -port 1521 \
  -user '<user>@<tenant>#<cluster>' \
  -password '<password>' \
  -oracle-mode \
  -full-test

The -oracle-mode flag forces Oracle mode when the server version string does not contain "oracle" (common with OBProxy).

MySQL Tenant — Full Integration Test (TLS)
go run ./cmd/obping \
  -host <host> \
  -port 3306 \
  -user '<user>' \
  -password '<password>' \
  -database <database> \
  -tls \
  -tls-ca /path/to/ca.pem \
  -mysql-mode \
  -full-test

The -tls flag enables TLS, and -tls-ca specifies the CA certificate path for verifying the server certificate.

Full-Test Reference

The -full-test flag runs 16 test categories in sequence:

# Test Description
1 Ping Basic connectivity check
2 Numeric SELECT 1.5 + 2.3 FROM DUAL
3 String SELECT UPPER('hello world') FROM DUAL
4 Timestamp SELECT CURRENT_TIMESTAMP FROM DUAL
5 DDL CREATE TABLE with INTEGER/VARCHAR/TIMESTAMP columns
6 INSERT INSERT 3 rows with ? placeholders
7 SELECT Multi-row SELECT ... ORDER BY
8 Param Query SELECT ... WHERE id = ? (text protocol interpolation)
9 Prepared ? Server-side prepared statement with ? (Oracle mode only)
10 Prepared :1 Server-side prepared statement with :1 (Oracle mode only)
11 UPDATE UPDATE ... WHERE id = ?
12 DELETE DELETE ... WHERE id = ?
13 NULL INSERT/SELECT NULL values
14 Rollback Transaction UPDATE + ROLLBACK, verify no change
15 Commit Transaction INSERT + COMMIT, verify persistence
16 Cleanup DROP test table

Note: Tests 9-10 (prepared statements) use COM_STMT_EXECUTE which is not supported by some OBProxy versions (notably MySQL-mode OBProxy). In Oracle mode through OBProxy, prepared statements work correctly. Failures in tests 9-10 are non-fatal — the connection is isolated and cleaned up before continuing.

Using obping for Regression Testing

The -full-test flag is designed for regression testing. After any code changes, run:

Oracle tenant:

obping \
  -host <host> -port 1521 \
  -user '<user>' -password '<password>' \
  -oracle-mode \
  -full-test

MySQL tenant:

obping \
  -host <host> -port 3306 \
  -user '<user>' -password '<password>' \
  -database <database> \
  -tls -tls-ca /path/to/ca.pem \
  -mysql-mode \
  -full-test

Expected result: === ALL TESTS PASSED ===

Security

Never commit real database credentials, hostnames, or certificates to the repository. Always use placeholder values (<host>, <user>, <password>, etc.) in documentation, issues, and PRs.

Driver Usage in Go Code

package main

import (
	"database/sql"
	_ "github.com/helingjun/obconnector-go"
)

func main() {
	db, err := sql.Open("oceanbase", "oceanbase://<user>:<password>@<host>:<port>/?timeout=5s")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	var one string
	if err := db.QueryRow("select 1 from dual").Scan(&one); err != nil {
		panic(err)
	}
}

Parameterized Query Support

Current ? parameter support is a client-side interpolation layer, not server-side prepared statements.

Supported parameter types:

  • nil
  • string
  • int64
  • float64
  • bool
  • []byte
  • time.Time

The interpolation logic correctly handles string literals, quoted identifiers, line comments, and block comments.

License

Apache-2.0. See LICENSE.

Documentation

Index

Constants

View Source
const Version = "0.2.1"

Variables

This section is empty.

Functions

func BulkInsert added in v0.2.0

func BulkInsert(ctx context.Context, db *sql.DB, tableName string, columns []string, values [][]any) (sql.Result, error)

BulkInsert is a helper to perform high-performance multi-row inserts. It uses native COM_STMT_BULK_EXECUTE if supported, otherwise rewrites the SQL.

func DefaultCollation

func DefaultCollation() byte

func NewConnector

func NewConnector(cfg Config) (driver.Connector, error)

func WithPartitionID added in v0.2.0

func WithPartitionID(ctx context.Context, id int64) context.Context

func WithSpanID added in v0.2.0

func WithSpanID(ctx context.Context, id string) context.Context

func WithTraceID added in v0.2.0

func WithTraceID(ctx context.Context, id string) context.Context

Types

type Config

type Config struct {
	Addr           string
	User           string
	Password       string
	Database       string
	Timeout        time.Duration
	Attributes     map[string]string
	CapabilityAdd  uint32
	CapabilityDrop uint32
	Collation      byte
	InitSQL        []string
	Preset         string
	Trace          bool
	TraceWriter    io.Writer
	ProtocolV2     bool
	OB20Magic      uint16
	TLSConfig      *tls.Config
}

func ParseDSN

func ParseDSN(dsn string) (*Config, error)

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

func (*Conn) Begin

func (c *Conn) Begin() (driver.Tx, error)

func (*Conn) BeginTx

func (c *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error)

func (*Conn) CheckNamedValue

func (c *Conn) CheckNamedValue(v *driver.NamedValue) error

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) ExecContext

func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error)

func (*Conn) IsValid

func (c *Conn) IsValid() bool

func (*Conn) Ping

func (c *Conn) Ping(ctx context.Context) error

func (*Conn) Prepare

func (c *Conn) Prepare(query string) (driver.Stmt, error)

func (*Conn) PrepareContext

func (c *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error)

func (*Conn) QueryContext

func (c *Conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error)

func (*Conn) ResetSession

func (c *Conn) ResetSession(ctx context.Context) error

type Connector

type Connector struct {
	// contains filtered or unexported fields
}

func (*Connector) Connect

func (c *Connector) Connect(ctx context.Context) (driver.Conn, error)

func (*Connector) Driver

func (c *Connector) Driver() driver.Driver

type Driver

type Driver struct{}

func (*Driver) Open

func (d *Driver) Open(name string) (driver.Conn, error)

func (*Driver) OpenConnector

func (d *Driver) OpenConnector(name string) (driver.Connector, error)

type Rows

type Rows struct {
	// contains filtered or unexported fields
}

func (*Rows) Close

func (r *Rows) Close() error

func (*Rows) ColumnTypeDatabaseTypeName

func (r *Rows) ColumnTypeDatabaseTypeName(index int) string

func (*Rows) ColumnTypeNullable

func (r *Rows) ColumnTypeNullable(index int) (nullable, ok bool)

func (*Rows) ColumnTypeScanType

func (r *Rows) ColumnTypeScanType(index int) reflect.Type

func (*Rows) Columns

func (r *Rows) Columns() []string

func (*Rows) Next

func (r *Rows) Next(dest []driver.Value) error

type ServerError

type ServerError struct {
	Number   uint16
	SQLState string
	Message  string
}

func (*ServerError) Error

func (e *ServerError) Error() string

type Stmt

type Stmt struct {
	// contains filtered or unexported fields
}

func (*Stmt) BulkExecContext added in v0.2.0

func (s *Stmt) BulkExecContext(ctx context.Context, argRows [][]driver.NamedValue) (driver.Result, error)

func (*Stmt) Close

func (s *Stmt) Close() error

func (*Stmt) Exec

func (s *Stmt) Exec(args []driver.Value) (driver.Result, error)

func (*Stmt) ExecContext

func (s *Stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error)

func (*Stmt) NumInput

func (s *Stmt) NumInput() int

func (*Stmt) Query

func (s *Stmt) Query(args []driver.Value) (driver.Rows, error)

func (*Stmt) QueryContext

func (s *Stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error)

type Tx

type Tx struct {
	// contains filtered or unexported fields
}

func (*Tx) Commit

func (tx *Tx) Commit() error

func (*Tx) Rollback

func (tx *Tx) Rollback() error

Directories

Path Synopsis
cmd
obping command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL