some how-to and why documentation

This commit is contained in:
Jim Lambert 2020-02-14 15:12:39 -05:00
parent 3f9a0298ab
commit 665549e1bc
2 changed files with 212 additions and 0 deletions

164
dialects/oci8/README.md Normal file
View File

@ -0,0 +1,164 @@
# oci8 dialect
- [oci8 dialect](#oci8-dialect)
- [Overview](#overview)
- [Install oracle client (required by go module)](#install-oracle-client-required-by-go-module)
- [Install the Module](#install-the-module)
- [Basic Test](#basic-test)
- [Running Oracle in Docker](#running-oracle-in-docker)
## Overview
This document covers everything you need to install/configure/run to get the oci8 dialect up and running.
You'll find some additional documentation on various challenges and design decisions for the dialect in [doc.go](./doc.go)
## Install oracle client (required by go module)
Download instaclients from: https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html
You need the basic, sqlplus and sdk packages.
Move the zip instaclient files to `~/Library/Caches/Homebrew`
Install the clients with brew
```
$ brew tap InstantClientTap/instantclient
$ brew install instantclient-basic
$ brew install instantclient-sqlplus
$ brew install instantclient-sdk
```
## Install the Module
```
go get github.com/mattn/go-oci8
```
Install pkg-config via brew
```
$ brew install pkg-config
```
Create `/usr/local/lib/pkgconfig/oci8.pc`
Contents:
```
prefixdir=/usr/local/lib
libdir=${prefixdir}
includedir=${prefixdir}/sdk/include
Name: OCI
Description: Oracle database driver
Version: 12.2
Libs: -L${libdir} -lclntsh
Cflags: -I${includedir}%
```
Test pkg-config for oci8
```
$ pkg-config --cflags --libs oci8
-I/usr/local/lib/sdk/include -L/usr/local/lib -lclntsh
```
### Basic Test
Once you've got Oracle up and running and you've created the gorm user with appropriate privs, try to run:
```
# chdir to the oci8 dialect's directory:
$ cd dialect/oci8
# run a basic connection test
$ go test -v -run Test_Connection
=== RUN Test_Connection
--- PASS: Test_Connection (0.06s)
connection_test.go:29: The date is: 2020-02-14T20:09:37Z
PASS
ok github.com/jinzhu/gorm/dialects/oci8 1.609s
```
## Running Oracle in Docker
Download the Oracle Express Edition version 18c (xe) Linux rpm from oracle.com
```
git clone https://github.com/oracle/docker-images.git
```
copy binary you downloaded
```
cp ~/Dowloads/<image-name> ./18.4.0
```
build image
```
./buildDockerImage.sh -x -v 18.4.0
```
start container
```
docker run -dit --name oracledb \
-p 1521:1521 -p 5500:5500 -p 8080:8080 \
-e ORACLE_PWD=oracle \
-v $HOME/oracle/oradata:/opt/oracle/oradata \
oracle/database:18.4.0-xe
```
Check logs and wait for oracle to be ready…
```
docker logs -f oracledb
The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
```
Connect via sqlplus as sysdba via container
```
docker exec -it oracledb sqlplus sys/oracle@localhost:1521/XE as sysdba
SQL*Plus: Release 18.0.0.0.0 - Production on Mon Feb 10 16:33:44 2020
Version 18.4.0.0.0
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Connected to:
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0
SQL>
```
Connect via sqlplus as system user via container:
```
docker exec -it oracledb sqlplus system/oracle@localhost:1521/XE
SQL*Plus: Release 18.0.0.0.0 - Production on Mon Feb 10 17:08:04 2020
Version 18.4.0.0.0
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Last Successful login time: Mon Feb 10 2020 17:07:07 +00:00
Connected to:
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0
SQL>
```
create a gorm user
```
docker exec -it oracledb sqlplus system/oracle@localhost:1521/XE
SQL>
-- creating user in the default PDB
ALTER SESSION SET CONTAINER = XEPDB1;
create user gorm identified by gorm;
-- we need some privs
GRANT CONNECT, RESOURCE, DBA TO gorm;
GRANT CREATE SESSION TO gorm;
GRANT UNLIMITED TABLESPACE TO gorm;
```

48
dialects/oci8/doc.go Normal file
View File

@ -0,0 +1,48 @@
package oci8
/*
Understanding Oracle
It's a bit different than the other RDBMS databases and I'll just try to
hightlight a few of the important ones the dialect has to deal with:
1. Oracle upper cases all non-quoted identifiers. That means the dialect
has to decide what to do:
1. quote all identifiers which would require developers to quote every
identifer they passed in a string to gorm.
2. only quote identifers that conflict with reserved words and leave all
other identifiers unquoted, which means Oracle will automatically
upper case them. This would allow developers to pass unquoted
identifiers in strings they passed to gorm and make the experience
align better with the other dialects.
We chose option #2.
This design decision has the following side affects:
a. you must be case insensitive when matching column names, like in
the Scope.scan function
b. Devs will have to escape reserved words when they reference them
in things like: First(&CreditCard{}, `"number" = ?`)
2. Oracle handles last inserted id a bit differently, and requires a sql.Out
parameter to return the value. Since Oracle parameters are positional, you
need to know how many other bind variables there are before adding the returning
clause. (see createCallback() )
3. Oracle doesn't let you specify "AS <tablename> " when selecting a count
from a dynamic table, so you just omit it. (see Scope.count() )
4. Oracle handles foreign keys a bit differently:
A. REFERENCES is implicit
B. ON UPDATE is not supported
(see scope.addForeignKey() )
5. Searching a blob requires using a function from the dbms_lob package like
instr() and specifying the offset and number of matches.
(see oci8.SearchBlob() )
6 Trailing semicolons are not allowed at the end of Oracle sql statements
(so they were removed in the unit tests)
*/