Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New test case for procedures #25

Merged
merged 4 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/sqlJob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ export class SQLJob {
*/
constructor(public options: JDBCOptions = {}) {}

/**
* Enables local tracing of the channel data.
*/
enableLocalTrace() {
this.isTracingChannelData = true
}

/**
* Establishes a WebSocket connection to the specified DB2 server.
*
Expand Down
36 changes: 33 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,28 @@ export interface SetConfigResult extends ServerResponse {
tracelevel: ServerTraceLevel;
}

export interface ParameterDetail {
type: string;
mode: "IN"| "OUT" | "INOUT";
precision: number;
scale?: number;
name: string;
}

export interface ParameterResult {
index: number;
type: string;
precision: number;
scale?: number;
name: string;

/** CCSID of the parameter result */
ccsid?: number;

/** Value is only available for OUT/INOUT */
value?: any;
}

/** Interface representing a standard query result. */
export interface QueryResult<T> extends ServerResponse {
/** Metadata about the query results. */
Expand All @@ -166,6 +188,12 @@ export interface QueryResult<T> extends ServerResponse {

/** Data returned from the query. */
data: T[];

/** Parameters returned from the query. */
worksofliam marked this conversation as resolved.
Show resolved Hide resolved
parameter_count?: number;

/** Parameters returned from the query. */
output_parms?: ParameterResult[];
}

/** Interface representing a log entry from a job. */
Expand Down Expand Up @@ -204,13 +232,15 @@ export interface CLCommandResult extends ServerResponse {
/** Interface representing metadata about a query. */
export interface QueryMetaData {
/** Number of columns returned by the query. */
column_count: number;
column_count?: number;

/** Metadata for each column. */
columns: ColumnMetaData[];
columns?: ColumnMetaData[];

parameters?: ParameterDetail[];

/** Unique job identifier for the query. */
job: string;
job?: string;
}

/** Interface representing metadata for a single column in a query result. */
Expand Down
182 changes: 182 additions & 0 deletions test/procedures.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { beforeAll, expect, test } from "vitest";
import { DaemonServer } from "../src/types";
import { SQLJob } from "../src";
import { getCertificate } from "../src/tls";
import { ENV_CREDS } from "./env";

let creds: DaemonServer = { ...ENV_CREDS };

const TEST_SCHEMA = `mapepire_test`;

beforeAll(async () => {
const ca = await getCertificate(creds);
creds.ca = ca.raw;

const job = new SQLJob();
await job.connect(creds);

const schemaQuery = job.query<any[]>(`create schema ${TEST_SCHEMA}`);

try {
await schemaQuery.execute();
} catch (e) {
// ignore
} finally {
await schemaQuery.close();
}
});

test(`IN, OUT, INOUT number parameters`, async () => {
const job = new SQLJob();
await job.connect(creds);

const testProc = `
create or replace procedure ${TEST_SCHEMA}.procedure_test(
in p1 integer,
inout p2 integer,
out p3 integer
)
BEGIN
set p3 = p1 + p2;
set p2 = 0;
END
`;

const queryA = job.query<any[]>(testProc);
await queryA.execute();
await queryA.close();

const queryB = job.query<any[]>(`call ${TEST_SCHEMA}.procedure_test(?, ?, ?)`, {parameters: [6, 4, 0]});
const result = await queryB.execute();
await queryB.close();

expect(result.metadata.parameters).toBeDefined();
const inParmNames = result.metadata.parameters.map(p => p.name);
const inParmTypes = result.metadata.parameters.map(p => p.type);
expect(inParmNames).toEqual(["P1", "P2", "P3"]);
expect(inParmTypes).toEqual(["INTEGER", "INTEGER", "INTEGER"]);

expect(result.success).toBe(true);
expect(result.parameter_count).toBe(3);
expect(result.update_count).toBe(0);
expect(result.has_results).toBe(false);
expect(result.data.length).toBe(0);

expect(result.output_parms).toBeDefined();
expect(result.output_parms.length).toBe(3);
const outParmNames = result.output_parms.map(p => p.name);
const outParmTypes = result.output_parms.map(p => p.type);
const outParmValues = result.output_parms.map(p => p.value);

expect(outParmNames).toEqual(["P1", "P2", "P3"]);
expect(outParmTypes).toEqual(["INTEGER", "INTEGER", "INTEGER"]);
expect(outParmValues).toEqual([undefined, 0, 10]);

await job.close();
});

test(`IN, OUT, INOUT char parameters`, async () => {
const job = new SQLJob();
await job.connect(creds);

const testProc = `
create or replace procedure ${TEST_SCHEMA}.procedure_test_char(
in p1 char(5),
inout p2 char(6),
out p3 char(7)
)
BEGIN
set p3 = rtrim(p1) concat rtrim(p2);
set p2 = '';
END
`;

const queryA = job.query<any[]>(testProc);
await queryA.execute();
await queryA.close();

const queryB = job.query<any[]>(`call ${TEST_SCHEMA}.procedure_test_char(?, ?, ?)`, {parameters: ['a', 'b', '']});
const result = await queryB.execute();
await queryB.close();

expect(result.metadata.parameters).toBeDefined();
const inParmNames = result.metadata.parameters.map(p => p.name);
const inParmTypes = result.metadata.parameters.map(p => p.type);
const inPrecisions = result.metadata.parameters.map(p => p.precision);
expect(inParmNames).toEqual(["P1", "P2", "P3"]);
expect(inParmTypes).toEqual(["CHAR", "CHAR", "CHAR"]);
expect(inPrecisions).toEqual([5, 6, 7]);

expect(result.success).toBe(true);
expect(result.parameter_count).toBe(3);
expect(result.update_count).toBe(0);
expect(result.has_results).toBe(false);
expect(result.data.length).toBe(0);

expect(result.output_parms).toBeDefined();
expect(result.output_parms.length).toBe(3);
const outParmNames = result.output_parms.map(p => p.name);
const outParmTypes = result.output_parms.map(p => p.type);
const outParmPrecisions = result.output_parms.map(p => p.precision);
const outParmValues = result.output_parms.map(p => p.value);

expect(outParmNames).toEqual(["P1", "P2", "P3"]);
expect(outParmTypes).toEqual(["CHAR", "CHAR", "CHAR"]);
expect(outParmPrecisions).toEqual([5, 6, 7]);
expect(outParmValues).toEqual([undefined, '', 'ab']);

await job.close();
});

test(`IN, OUT, INOUT varchar parameters`, async () => {
const job = new SQLJob();
await job.connect(creds);

const testProc = `
create or replace procedure ${TEST_SCHEMA}.procedure_test_varchar(
in p1 varchar(5),
inout p2 varchar(6),
out p3 varchar(7)
)
BEGIN
set p3 = p1 concat p2;
set p2 = '';
END
`;

const queryA = job.query<any[]>(testProc);
await queryA.execute();
await queryA.close();

const queryB = job.query<any[]>(`call ${TEST_SCHEMA}.procedure_test_varchar(?, ?, ?)`, {parameters: ['a', 'b', '']});
const result = await queryB.execute();
await queryB.close();

expect(result.metadata.parameters).toBeDefined();
const inParmNames = result.metadata.parameters.map(p => p.name);
const inParmTypes = result.metadata.parameters.map(p => p.type);
const inPrecisions = result.metadata.parameters.map(p => p.precision);
expect(inParmNames).toEqual(["P1", "P2", "P3"]);
expect(inParmTypes).toEqual(["VARCHAR", "VARCHAR", "VARCHAR"]);
expect(inPrecisions).toEqual([5, 6, 7]);

expect(result.success).toBe(true);
expect(result.parameter_count).toBe(3);
expect(result.update_count).toBe(0);
expect(result.has_results).toBe(false);
expect(result.data.length).toBe(0);

expect(result.output_parms).toBeDefined();
expect(result.output_parms.length).toBe(3);
const outParmNames = result.output_parms.map(p => p.name);
const outParmTypes = result.output_parms.map(p => p.type);
const outParmPrecisions = result.output_parms.map(p => p.precision);
const outParmValues = result.output_parms.map(p => p.value);

expect(outParmNames).toEqual(["P1", "P2", "P3"]);
expect(outParmTypes).toEqual(["VARCHAR", "VARCHAR", "VARCHAR"]);
expect(outParmPrecisions).toEqual([5, 6, 7]);
expect(outParmValues).toEqual([undefined, '', 'ab']);

await job.close();
});
Loading