Add oracledb package, readme, and config
This commit is contained in:
parent
b5b191361d
commit
cb661eab34
|
@ -106,6 +106,7 @@
|
||||||
"mysql2": "^2.3.1",
|
"mysql2": "^2.3.1",
|
||||||
"node-fetch": "2.6.0",
|
"node-fetch": "2.6.0",
|
||||||
"open": "7.3.0",
|
"open": "7.3.0",
|
||||||
|
"oracledb": "^5.3.0",
|
||||||
"pg": "8.5.1",
|
"pg": "8.5.1",
|
||||||
"pino-pretty": "4.0.0",
|
"pino-pretty": "4.0.0",
|
||||||
"posthog-node": "^1.1.4",
|
"posthog-node": "^1.1.4",
|
||||||
|
@ -133,6 +134,7 @@
|
||||||
"@types/koa": "^2.13.3",
|
"@types/koa": "^2.13.3",
|
||||||
"@types/koa-router": "^7.4.2",
|
"@types/koa-router": "^7.4.2",
|
||||||
"@types/node": "^15.12.4",
|
"@types/node": "^15.12.4",
|
||||||
|
"@types/oracledb": "^5.2.1",
|
||||||
"@typescript-eslint/parser": "4.28.0",
|
"@typescript-eslint/parser": "4.28.0",
|
||||||
"babel-jest": "^27.0.2",
|
"babel-jest": "^27.0.2",
|
||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
docker-compose down
|
|
||||||
docker volume prune -f
|
|
|
@ -11,7 +11,7 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
volumes:
|
volumes:
|
||||||
#- pg_data:/var/lib/postgresql/data/
|
- pg_data:/var/lib/postgresql/data/
|
||||||
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
|
||||||
pgadmin:
|
pgadmin:
|
||||||
|
@ -24,5 +24,5 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "5050:80"
|
- "5050:80"
|
||||||
|
|
||||||
#volumes:
|
volumes:
|
||||||
# pg_data:
|
pg_data:
|
||||||
|
|
|
@ -45,6 +45,7 @@ export enum SourceNames {
|
||||||
MYSQL = "MYSQL",
|
MYSQL = "MYSQL",
|
||||||
ARANGODB = "ARANGODB",
|
ARANGODB = "ARANGODB",
|
||||||
REST = "REST",
|
REST = "REST",
|
||||||
|
ORACLE = "ORACLE",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IncludeRelationships {
|
export enum IncludeRelationships {
|
||||||
|
|
|
@ -290,4 +290,5 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default SqlQueryBuilder
|
||||||
module.exports = SqlQueryBuilder
|
module.exports = SqlQueryBuilder
|
||||||
|
|
|
@ -9,6 +9,7 @@ const airtable = require("./airtable")
|
||||||
const mysql = require("./mysql")
|
const mysql = require("./mysql")
|
||||||
const arangodb = require("./arangodb")
|
const arangodb = require("./arangodb")
|
||||||
const rest = require("./rest")
|
const rest = require("./rest")
|
||||||
|
const oracle = require("./oracle")
|
||||||
const { SourceNames } = require("../definitions/datasource")
|
const { SourceNames } = require("../definitions/datasource")
|
||||||
|
|
||||||
const DEFINITIONS = {
|
const DEFINITIONS = {
|
||||||
|
@ -23,6 +24,7 @@ const DEFINITIONS = {
|
||||||
[SourceNames.MYSQL]: mysql.schema,
|
[SourceNames.MYSQL]: mysql.schema,
|
||||||
[SourceNames.ARANGODB]: arangodb.schema,
|
[SourceNames.ARANGODB]: arangodb.schema,
|
||||||
[SourceNames.REST]: rest.schema,
|
[SourceNames.REST]: rest.schema,
|
||||||
|
[SourceNames.ORACLE]: oracle.schema,
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTEGRATIONS = {
|
const INTEGRATIONS = {
|
||||||
|
@ -37,6 +39,7 @@ const INTEGRATIONS = {
|
||||||
[SourceNames.MYSQL]: mysql.integration,
|
[SourceNames.MYSQL]: mysql.integration,
|
||||||
[SourceNames.ARANGODB]: arangodb.integration,
|
[SourceNames.ARANGODB]: arangodb.integration,
|
||||||
[SourceNames.REST]: rest.integration,
|
[SourceNames.REST]: rest.integration,
|
||||||
|
[SourceNames.ORACLE]: oracle.integration,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -8,20 +8,29 @@ import {
|
||||||
import { Table } from "../definitions/common"
|
import { Table } from "../definitions/common"
|
||||||
import { getSqlQuery } from "./utils"
|
import { getSqlQuery } from "./utils"
|
||||||
import { DatasourcePlus } from "./base/datasourcePlus"
|
import { DatasourcePlus } from "./base/datasourcePlus"
|
||||||
|
import oracledb, { Result } from "oracledb"
|
||||||
module OracleModule {
|
import { Connection } from "oracledb"
|
||||||
// TODO: oracle js lib
|
import Sql from "./base/sql"
|
||||||
// const connection = require("oracle")
|
import { FieldTypes } from "../constants"
|
||||||
const Sql = require("./base/sql")
|
import {
|
||||||
const { FieldTypes } = require("../constants")
|
|
||||||
const {
|
|
||||||
buildExternalTableId,
|
buildExternalTableId,
|
||||||
convertType,
|
convertType,
|
||||||
finaliseExternalTables,
|
finaliseExternalTables
|
||||||
} = require("./utils")
|
} from "./utils"
|
||||||
|
|
||||||
|
module OracleModule {
|
||||||
|
|
||||||
|
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;
|
||||||
|
|
||||||
interface OracleConfig {
|
interface OracleConfig {
|
||||||
// TODO: Connection config
|
host: string
|
||||||
|
port: number
|
||||||
|
database: string
|
||||||
|
user: string
|
||||||
|
password: string
|
||||||
|
// ssl?: boolean
|
||||||
|
// ca?: string
|
||||||
|
// rejectUnauthorized?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const SCHEMA: Integration = {
|
const SCHEMA: Integration = {
|
||||||
|
@ -30,10 +39,57 @@ module OracleModule {
|
||||||
friendlyName: "Oracle",
|
friendlyName: "Oracle",
|
||||||
description: "description",
|
description: "description",
|
||||||
datasource: {
|
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: {
|
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
|
// TODO: type map
|
||||||
}
|
}
|
||||||
|
|
||||||
async function internalQuery(client: any, query: SqlQuery) {
|
const internalQuery = async (connection: Connection, query: SqlQuery): Promise<Result<any> | null>=> {
|
||||||
// TODO: Use oracle lib to run query
|
try {
|
||||||
const rows = []
|
const result: Result<any> = await connection.execute(
|
||||||
|
`SELECT manager_id, department_id, department_name
|
||||||
return rows
|
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 {
|
class OracleIntegration extends Sql implements DatasourcePlus {
|
||||||
|
@ -57,7 +129,17 @@ module OracleModule {
|
||||||
constructor(config: OracleConfig) {
|
constructor(config: OracleConfig) {
|
||||||
super("oracle")
|
super("oracle")
|
||||||
this.config = config
|
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) {
|
async query(json: QueryJson) {
|
||||||
const operation = this._operation(json).toLowerCase()
|
const operation = this._operation(json).toLowerCase()
|
||||||
const input = this._query(json)
|
const input = this._query(json)
|
||||||
const response = await internalQuery(this.client, input)
|
const connection = await this.getConnection()
|
||||||
return response.rows.length ? response.rows : [{ [operation]: true }]
|
const result = await internalQuery(connection, input)
|
||||||
|
if (result && result.rows && result.rows.length) {
|
||||||
|
return result.rows
|
||||||
|
} else {
|
||||||
|
return [{ [operation]: true }]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2262,6 +2262,14 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3"
|
||||||
integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==
|
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":
|
"@types/prettier@^2.1.5":
|
||||||
version "2.3.2"
|
version "2.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3"
|
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"
|
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||||
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
|
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:
|
double-ended-queue@2.1.0-0:
|
||||||
version "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"
|
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"
|
type-check "~0.3.2"
|
||||||
word-wrap "~1.2.3"
|
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:
|
os-locale@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
|
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
|
||||||
|
|
Loading…
Reference in New Issue