Add oracle test

This commit is contained in:
Lunny Xiao 2024-04-02 14:02:30 +08:00
parent 589acfff86
commit afb3b44b83
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
4 changed files with 132 additions and 6 deletions

View File

@ -0,0 +1,38 @@
name: test oracle
on:
push:
branches:
- main
pull_request:
jobs:
lint:
name: test oracle
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: test oracle
env:
TEST_ORACLE_HOST: oracle:1521
TEST_ORACLE_DBNAME: FREEPDB1
TEST_ORACLE_USERNAME: system
TEST_ORACLE_PASSWORD: oracle
run: TEST_CACHE_ENABLE=false make test-oracle
services:
oracle:
image: gvenzl/oracle-xe:latest
env:
ORACLE_RANDOM_PASSWORD: true
APP_USER: system
APP_USER_PASSWORD: oracle
ports:
- 1521:1521
options: >-
--health-cmd healthcheck.sh
--health-interval 10s
--health-timeout 5s
--health-retries 10

View File

@ -48,6 +48,12 @@ TEST_DAMENG_HOST ?= dameng:5236
TEST_DAMENG_USERNAME ?= SYSDBA TEST_DAMENG_USERNAME ?= SYSDBA
TEST_DAMENG_PASSWORD ?= SYSDBA TEST_DAMENG_PASSWORD ?= SYSDBA
TEST_ORACLE_HOST ?= oracle:1521
TEST_ORACLE_SCHEMA ?=
TEST_ORACLE_DBNAME ?= xe
TEST_ORACLE_USERNAME ?= system
TEST_ORACLE_PASSWORD ?= oracle
TEST_CACHE_ENABLE ?= false TEST_CACHE_ENABLE ?= false
TEST_QUOTE_POLICY ?= always TEST_QUOTE_POLICY ?= always
@ -279,6 +285,21 @@ test-dameng\#%: go-check
-conn_str="dm://$(TEST_DAMENG_USERNAME):$(TEST_DAMENG_PASSWORD)@$(TEST_DAMENG_HOST)" \ -conn_str="dm://$(TEST_DAMENG_USERNAME):$(TEST_DAMENG_PASSWORD)@$(TEST_DAMENG_HOST)" \
-coverprofile=dameng.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -coverprofile=dameng.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m
.PHONY: test-oracle
test-oracle: test-goora
.PNONY: test-goora
test-goora: go-check
$(GO) test $(INTEGRATION_PACKAGES) -v -race -db=goora -schema='$(TEST_ORACLE_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="$(TEST_ORACLE_USERNAME):$(TEST_ORACLE_PASSWORD)@$(TEST_ORACLE_HOST)/$(TEST_ORACLE_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-oci8\#%
test-goora\#%: go-check
$(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=goora -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="oracle://$(TEST_ORACLE_USERNAME):$(TEST_ORACLE_PASSWORD)@$(TEST_ORACLE_HOST)/$(TEST_ORACLE_DBNAME)" \
-coverprofile=oracle.$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: vet .PHONY: vet
vet: vet:
$(GO) vet $(shell $(GO) list ./...) $(GO) vet $(shell $(GO) list ./...)

View File

@ -14,6 +14,7 @@ import (
"strings" "strings"
"xorm.io/xorm/core" "xorm.io/xorm/core"
"xorm.io/xorm/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/schemas"
) )
@ -567,11 +568,13 @@ func (db *oracle) SQLType(c *schemas.Column) string {
c.Default = "0" c.Default = "0"
} }
res = "NUMBER(1,0)" res = "NUMBER(1,0)"
case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, schemas.Serial, schemas.BigSerial: case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int,
schemas.Integer, schemas.BigInt, schemas.Serial, schemas.BigSerial,
schemas.UnsignedBigInt, schemas.UnsignedBit, schemas.UnsignedInt:
res = "NUMBER" res = "NUMBER"
case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea: case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea:
return schemas.Blob return schemas.Blob
case schemas.Time, schemas.DateTime, schemas.TimeStamp: case schemas.Date, schemas.Time, schemas.DateTime, schemas.TimeStamp:
res = schemas.TimeStamp res = schemas.TimeStamp
case schemas.TimeStampz: case schemas.TimeStampz:
res = "TIMESTAMP WITH TIME ZONE" res = "TIMESTAMP WITH TIME ZONE"
@ -695,9 +698,29 @@ func (db *oracle) IsColumnExist(queryer core.Queryer, ctx context.Context, table
return db.HasRecords(queryer, ctx, query, args...) return db.HasRecords(queryer, ctx, query, args...)
} }
func QueryRowContext(ctx context.Context, queryer core.Queryer, query string, args ...interface{}) *core.Row {
rows, err := queryer.QueryContext(ctx, query, args...)
if err != nil {
return core.NewRow(nil, err)
}
return core.NewRow(rows, nil)
}
func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
s := `select column_name from user_cons_columns
where constraint_name = (select constraint_name from user_constraints
where table_name = :1 and constraint_type ='P')`
var pkName string
err := QueryRowContext(ctx, queryer, s, tableName).Scan(&pkName)
if err != nil {
if err == sql.ErrNoRows {
err = nil
}
return nil, nil, err
}
args := []interface{}{tableName} args := []interface{}{tableName}
s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," + s = "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
"nullable FROM USER_TAB_COLUMNS WHERE table_name = :1" "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
rows, err := queryer.QueryContext(ctx, s, args...) rows, err := queryer.QueryContext(ctx, s, args...)
@ -712,11 +735,11 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col := new(schemas.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string var colName, colDefault, nullable, dataType, dataPrecision, dataScale, comment *string
var dataLen int64 var dataLen int64
err = rows.Scan(&colName, &colDefault, &dataType, &dataLen, &dataPrecision, err = rows.Scan(&colName, &colDefault, &dataType, &dataLen, &dataPrecision,
&dataScale, &nullable) &dataScale, &nullable, &comment)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -733,6 +756,21 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col.Nullable = false col.Nullable = false
} }
if comment != nil {
col.Comment = *comment
}
if pkName != "" && pkName == col.Name {
col.IsPrimaryKey = true
has, err := db.HasRecords(queryer, ctx, "SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = :1", utils.SeqName(tableName))
if err != nil {
return nil, nil, err
}
if has {
col.IsAutoIncrement = true
}
}
var ignore bool var ignore bool
var dt string var dt string
@ -758,7 +796,7 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
case "NUMBER": case "NUMBER":
col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2}
case "LONG", "LONG RAW": case "LONG", "LONG RAW", "NCLOB", "CLOB":
col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0}
case "RAW": case "RAW":
col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}

View File

@ -111,6 +111,35 @@ func createEngine(dbType, connStr string) error {
} }
connStr = u.Path connStr = u.Path
*ignoreSelectUpdate = true *ignoreSelectUpdate = true
case schemas.ORACLE, "goora":
db, err := sql.Open("oracle", connStr)
if err != nil {
return err
}
rows, err := db.Query("SELECT 1 FROM pg_database WHERE datname = 'xorm_test'")
if err != nil {
return fmt.Errorf("db.Query: %v", err)
}
defer rows.Close()
if !rows.Next() {
if _, err = db.Exec("CREATE DATABASE xorm_test"); err != nil {
return fmt.Errorf("CREATE DATABASE: %v", err)
}
}
if *schema != "" {
db.Close()
db, err = sql.Open(dbType, connStr)
if err != nil {
return err
}
defer db.Close()
if _, err = db.Exec("CREATE SCHEMA IF NOT EXISTS " + *schema); err != nil {
return fmt.Errorf("CREATE SCHEMA: %v", err)
}
}
db.Close()
*ignoreSelectUpdate = true
default: default:
*ignoreSelectUpdate = true *ignoreSelectUpdate = true
} }