Add oracledb package, readme, and config

This commit is contained in:
Rory Powell 2021-11-05 13:56:54 +00:00
parent b78388f771
commit ab1fb07f86
9 changed files with 202 additions and 27 deletions

View File

@ -106,6 +106,7 @@
"mysql2": "^2.3.1",
"node-fetch": "2.6.0",
"open": "7.3.0",
"oracledb": "^5.3.0",
"pg": "8.5.1",
"pino-pretty": "4.0.0",
"posthog-node": "^1.1.4",
@ -133,6 +134,7 @@
"@types/koa": "^2.13.3",
"@types/koa-router": "^7.4.2",
"@types/node": "^15.12.4",
"@types/oracledb": "^5.2.1",
"@typescript-eslint/parser": "4.28.0",
"babel-jest": "^27.0.2",
"copyfiles": "^2.4.1",

View File

@ -0,0 +1,66 @@
### Installation & Management
To install oracle express edition simply run `docker-compose up`
- A single instance pluggable database (PDB) will be created named `xepdb`
- The default password is configured in the compose file as `oracle`
- The `system`, `sys` and `pdbadmin` users all share this password
To connect to oracle sql command line:
```bash
docker exec -it oracle-xe sqlplus -l system/oracle@localhost/xepdb1
```
To create a new schema (user = schema in oracle)
```sql
define USERNAME = rpowell
create user &USERNAME;
alter user &USERNAME
default tablespace users
temporary tablespace temp
quota unlimited on users;
grant create session,
create view,
create sequence,
create procedure,
create table,
create trigger,
create type,
create materialized view
to &USERNAME;
```
To set the password
```sql
define USERNAME = rpowell
define PASSWORD = rpowell
alter user &USERNAME identified by &PASSWORD;
```
As before the database schema can now be connected to
```bash
docker exec -it oracle-xe sqlplus -l rpowell/rpowell@localhost:1521/xepdb1
```
### Oracle Instant Client
Before oracle can be connected to from nodejs, the oracle client must be installed.
<!-- TODO: instructions -->
### HR Schema
The `HR` schema is populated with dummy data by default in oracle for testing purposes.
To connect to the HR schema first update the user password and unlock the account by performing
```sql
ALTER USER hr ACCOUNT UNLOCK;
ALTER USER hr IDENTIFIED BY hr
```
You should now be able to connect to the hr schema using the credentials hr/hr

View File

@ -1,3 +0,0 @@
#!/bin/bash
docker-compose down
docker volume prune -f

View File

@ -11,7 +11,7 @@ services:
ports:
- "5432:5432"
volumes:
#- pg_data:/var/lib/postgresql/data/
- pg_data:/var/lib/postgresql/data/
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
pgadmin:
@ -24,5 +24,5 @@ services:
ports:
- "5050:80"
#volumes:
# pg_data:
volumes:
pg_data:

View File

@ -45,6 +45,7 @@ export enum SourceNames {
MYSQL = "MYSQL",
ARANGODB = "ARANGODB",
REST = "REST",
ORACLE = "ORACLE",
}
export enum IncludeRelationships {

View File

@ -290,4 +290,5 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
}
}
export default SqlQueryBuilder
module.exports = SqlQueryBuilder

View File

@ -9,6 +9,7 @@ const airtable = require("./airtable")
const mysql = require("./mysql")
const arangodb = require("./arangodb")
const rest = require("./rest")
const oracle = require("./oracle")
const { SourceNames } = require("../definitions/datasource")
const DEFINITIONS = {
@ -23,6 +24,7 @@ const DEFINITIONS = {
[SourceNames.MYSQL]: mysql.schema,
[SourceNames.ARANGODB]: arangodb.schema,
[SourceNames.REST]: rest.schema,
[SourceNames.ORACLE]: oracle.schema,
}
const INTEGRATIONS = {
@ -37,6 +39,7 @@ const INTEGRATIONS = {
[SourceNames.MYSQL]: mysql.integration,
[SourceNames.ARANGODB]: arangodb.integration,
[SourceNames.REST]: rest.integration,
[SourceNames.ORACLE]: oracle.integration,
}
module.exports = {

View File

@ -8,20 +8,29 @@ import {
import { Table } from "../definitions/common"
import { getSqlQuery } from "./utils"
import { DatasourcePlus } from "./base/datasourcePlus"
module OracleModule {
// TODO: oracle js lib
// const connection = require("oracle")
const Sql = require("./base/sql")
const { FieldTypes } = require("../constants")
const {
import oracledb, { Result } from "oracledb"
import { Connection } from "oracledb"
import Sql from "./base/sql"
import { FieldTypes } from "../constants"
import {
buildExternalTableId,
convertType,
finaliseExternalTables,
} = require("./utils")
finaliseExternalTables
} from "./utils"
module OracleModule {
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;
interface OracleConfig {
// TODO: Connection config
host: string
port: number
database: string
user: string
password: string
// ssl?: boolean
// ca?: string
// rejectUnauthorized?: boolean
}
const SCHEMA: Integration = {
@ -30,10 +39,57 @@ module OracleModule {
friendlyName: "Oracle",
description: "description",
datasource: {
// TODO: datasource config
host: {
type: DatasourceFieldTypes.STRING,
default: "localhost",
required: true,
},
port: {
type: DatasourceFieldTypes.NUMBER,
required: true,
default: 1521,
},
database: {
type: DatasourceFieldTypes.STRING,
required: true,
},
user: {
type: DatasourceFieldTypes.STRING,
required: true,
},
password: {
type: DatasourceFieldTypes.PASSWORD,
required: true,
},
// ssl: {
// type: DatasourceFieldTypes.BOOLEAN,
// default: false,
// required: false,
// },
// rejectUnauthorized: {
// type: DatasourceFieldTypes.BOOLEAN,
// default: false,
// required: false,
// },
// ca: {
// type: DatasourceFieldTypes.LONGFORM,
// default: false,
// required: false,
// },
},
query: {
// TODO: query config
create: {
type: QueryTypes.SQL,
},
read: {
type: QueryTypes.SQL,
},
update: {
type: QueryTypes.SQL,
},
delete: {
type: QueryTypes.SQL,
},
},
}
@ -41,11 +97,27 @@ module OracleModule {
// TODO: type map
}
async function internalQuery(client: any, query: SqlQuery) {
// TODO: Use oracle lib to run query
const rows = []
return rows
const internalQuery = async (connection: Connection, query: SqlQuery): Promise<Result<any> | null>=> {
try {
const result: Result<any> = await connection.execute(
`SELECT manager_id, department_id, department_name
FROM departments
WHERE manager_id = :id`,
[103], // bind value for :id
);
return result
} catch (err) {
console.error(err);
return null
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.error(err);
}
}
}
}
class OracleIntegration extends Sql implements DatasourcePlus {
@ -57,7 +129,17 @@ module OracleModule {
constructor(config: OracleConfig) {
super("oracle")
this.config = config
//todo init client
}
getConnection = async (): Promise<Connection> => {
//connectString : "(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SID= ORCL)))"
const connectString = `${this.config.host}:${this.config.port || 1521}/${this.config.database}`
const config = {
user: this.config.user,
password: this.config.user,
connectString
}
return oracledb.getConnection(config);
}
/**
@ -112,8 +194,13 @@ module OracleModule {
async query(json: QueryJson) {
const operation = this._operation(json).toLowerCase()
const input = this._query(json)
const response = await internalQuery(this.client, input)
return response.rows.length ? response.rows : [{ [operation]: true }]
const connection = await this.getConnection()
const result = await internalQuery(connection, input)
if (result && result.rows && result.rows.length) {
return result.rows
} else {
return [{ [operation]: true }]
}
}
}

View File

@ -2262,6 +2262,14 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3"
integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==
"@types/oracledb@^5.2.1":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@types/oracledb/-/oracledb-5.2.1.tgz#b0c64d1ab68f1be6dc153a310ce0e840b8f333df"
integrity sha512-xtN24H9bpGB11ZiswZulAKYJ9xcWrF5BOAGFemcfeZkLmw8qAzVm+TAWT20VVLst6kh9VNxinY239S8EKgRBbA==
dependencies:
"@types/node" "*"
dotenv "^8.2.0"
"@types/prettier@^2.1.5":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3"
@ -4134,6 +4142,11 @@ dotenv@8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
dotenv@^8.2.0:
version "8.6.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
double-ended-queue@2.1.0-0:
version "2.1.0-0"
resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
@ -8261,6 +8274,11 @@ optionator@^0.8.1, optionator@^0.8.3:
type-check "~0.3.2"
word-wrap "~1.2.3"
oracledb@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-5.3.0.tgz#a15e6cd16757d8711a2c006a28bd7ecd3b8466f7"
integrity sha512-HMJzQ6lCf287ztvvehTEmjCWA21FQ3RMvM+mgoqd4i8pkREuqFWO+y3ovsGR9moJUg4T0xjcwS8rl4mggWPxmg==
os-locale@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"