Skip to content

Commit

Permalink
final fixes (#236)
Browse files Browse the repository at this point in the history
* final fixes

* Fixed test

* Correct tests

* Fixed

* Lint fixes

* Change to millis
  • Loading branch information
AsafMah authored Feb 14, 2023
1 parent 6852aab commit c487974
Show file tree
Hide file tree
Showing 9 changed files with 2,903 additions and 1,651 deletions.
4,441 changes: 2,823 additions & 1,618 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 9 additions & 2 deletions packages/azure-kusto-data/src/models.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { parseKustoTimestampToMillis } from "./timeUtils";

export enum WellKnownDataSet {
PrimaryResult = "PrimaryResult",
QueryCompletionInformation = "QueryCompletionInformation",
Expand All @@ -9,10 +11,10 @@ export enum WellKnownDataSet {
}

type DateTimeParser = (value: string) => any;
type TimeSpanParser = (value: number) => any;
type TimeSpanParser = (value: string) => any;

const defaultDatetimeParser: DateTimeParser = (t: string) => new Date(t);
const defaultTimespanParser: TimeSpanParser = (t: number) => t;
const defaultTimespanParser: TimeSpanParser = parseKustoTimestampToMillis;

export interface Table {
TableKind?: string;
Expand All @@ -28,6 +30,11 @@ interface Column {
DateType?: string;
}

/**
* Represents a Kusto result row.
* Use `dateTimeParser` and `timeSpanParser` to customize the parsing of the `datetime` and `timespan` types.
* By default, `datetime` is parsed to a `Date` object and `timespan` is parsed to a number representing the number of milliseconds, as returned by subtracting two `Date` objects.
*/
export class KustoResultRow {
columns: KustoResultColumn[];
raw: { [ord: number]: any };
Expand Down
19 changes: 19 additions & 0 deletions packages/azure-kusto-data/src/timeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,22 @@
export function toMilliseconds(hours: number, minutes: number, seconds: number) {
return (hours * 60 * 60 + minutes * 60 + seconds) * 1000;
}

// Format: [+|-]d.hh:mm:ss[.fffffff]
const TimespanRegex = /^(-?)(?:(\d+).)?(\d{2}):(\d{2}):(\d{2}(\.\d+)?$)/;

export function parseKustoTimestampToMillis(t: string | null): number {
if (t == null) {
return 0;
}
const match = TimespanRegex.exec(t);
if (match) {
const sign = match[1] === "-" ? -1 : 1;
const days = parseInt(match[2] || "0", 10);
const hours = parseInt(match[3], 10);
const minutes = parseInt(match[4], 10);
const seconds = parseFloat(match[5]);
return sign * 1000 * (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds);
}
throw new Error(`Timespan value '${t}' cannot be decoded`);
}
4 changes: 2 additions & 2 deletions packages/azure-kusto-data/test/data/response/v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@
}
],
"Rows": [
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, 0],
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.01:02:03.004"],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, null],
[null, "", null, null, null, null]
]
},
Expand Down
8 changes: 4 additions & 4 deletions packages/azure-kusto-data/test/data/response/v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ const a: [
}
];
Rows: [
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, 0],
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.01:02:03.004"],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, null],
[null, "", null, null, null, null]
];
},
Expand Down Expand Up @@ -227,8 +227,8 @@ const a: [
},
],
Rows: [
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, 0],
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.01:02:03.004"],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, null],
[null, "", null, null, null, null],
],
},
Expand Down
4 changes: 2 additions & 2 deletions packages/azure-kusto-data/test/data/response/v2error.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@
}
],
"Rows": [
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, 0],
["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.01:02:03.004"],
["2016-06-07T16:00:00Z", "bar", 555, 2.71, true, null],
[null, "", null, null, null, null]
]
},
Expand Down
63 changes: 42 additions & 21 deletions packages/azure-kusto-data/test/modelsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import assert from "assert";
import { KustoResultColumn, KustoResultRow, KustoResultTable } from "../src/models";
import v2 from "./data/response/v2";
import { parseKustoTimestampToMillis } from "../src/timeUtils";

const v2Response = v2;

Expand Down Expand Up @@ -39,15 +40,15 @@ describe("KustoResultRow", () => {
const inputColumns = rawColumns.map((c, i) => new KustoResultColumn(c, i));

it("initialize properly", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const actual = new KustoResultRow(inputColumns, inputValues);

assert.strictEqual(actual.columns.length, inputColumns.length);
});

it("column ordinal affects order", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const reverseOrderColumns = rawColumns.slice().reverse();
const actual = new KustoResultRow(
Expand All @@ -62,14 +63,12 @@ describe("KustoResultRow", () => {
inputValues[2],
inputValues[3],
inputValues[4],
new Date(inputValues[5] as number),
parseKustoTimestampToMillis(inputValues[5] as string),
];

for (let index = 0; index < inputColumns.length; index++) {
const currentActual = asJson[inputColumns[index].name as string];
if (inputColumns[index].type === "timespan") {
assert.strictEqual(Number(currentActual), Number(expectedValues[index]));
} else if (typeof currentActual === "object") {
if (typeof currentActual === "object") {
assert.strictEqual((currentActual as object).toString(), expectedValues[index].toString());
} else {
assert.strictEqual(currentActual, expectedValues[index]);
Expand All @@ -78,24 +77,22 @@ describe("KustoResultRow", () => {
});

it("custom parsers", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const reverseOrderColumns = rawColumns.slice().reverse();
const actual = new KustoResultRow(
reverseOrderColumns.map((c, i) => new KustoResultColumn(c, rawColumns.length - i - 1)),
inputValues,
(t) => t + "-date",
(t) => t + 5
(t) => t + "-time"
);

const asJson = actual.toJSON();
const expectedValues = ["2016-06-06T15:35:00Z-date", inputValues[1], inputValues[2], inputValues[3], inputValues[4], 3493235670005];
const expectedValues = ["2016-06-06T15:35:00Z-date", inputValues[1], inputValues[2], inputValues[3], inputValues[4], "1.02:03:04.567-time"];

for (let index = 0; index < inputColumns.length; index++) {
const currentActual = asJson[inputColumns[index].name as string];
if (inputColumns[index].type === "timespan") {
assert.strictEqual(Number(currentActual), Number(expectedValues[index]));
} else if (typeof currentActual === "object") {
if (typeof currentActual === "object") {
assert.strictEqual((currentActual as object).toString(), expectedValues[index].toString());
} else {
assert.strictEqual(currentActual, expectedValues[index]);
Expand All @@ -104,31 +101,31 @@ describe("KustoResultRow", () => {
});

it("mismatching data - less data than columns", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const actual = new KustoResultRow(inputColumns, inputValues);

assert.strictEqual(actual.columns.length, inputColumns.length);
});

it("mismatching data - less columns than data ", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const actual = new KustoResultRow(inputColumns, inputValues);

assert.strictEqual(actual.columns.length, inputColumns.length);
});

it("mismatching data - type mismatch ", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const actual = new KustoResultRow(inputColumns, inputValues);

assert.strictEqual(actual.columns.length, inputColumns.length);
});

it("iterate data", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const actual = new KustoResultRow(inputColumns, inputValues);

Expand All @@ -146,9 +143,9 @@ describe("KustoResultRow", () => {
});

it("mapped props", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const expectedValues = [new Date("2016-06-06T15:35:00Z"), "foo", 101, 3.14, false, 3493235670000];
const expectedValues = [new Date("2016-06-06T15:35:00Z"), "foo", 101, 3.14, false, 93784567];

const actual = new KustoResultRow(inputColumns, inputValues).toJSON<{
Timestamp: number;
Expand All @@ -168,9 +165,9 @@ describe("KustoResultRow", () => {
});

it("value at", () => {
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, 3493235670000];
const inputValues = ["2016-06-06T15:35:00Z", "foo", 101, 3.14, false, "1.02:03:04.567"];

const expectedValues = [new Date("2016-06-06T15:35:00Z"), "foo", 101, 3.14, false, 3493235670000];
const expectedValues = [new Date("2016-06-06T15:35:00Z"), "foo", 101, 3.14, false, 93784567];

const actual = new KustoResultRow(inputColumns, inputValues);

Expand Down Expand Up @@ -250,7 +247,7 @@ describe("KustoResultTable", () => {
it("iterate over rows with custom parsers", () => {
const actual = new KustoResultTable(v2Response[2]);
const dateParser = (t: string) => t + "-date";
const timeParser = (t: number) => t + 5;
const timeParser = (t: string) => t + "-time";
actual.dateTimeParser = dateParser;
actual.timeSpanParser = timeParser;

Expand All @@ -262,5 +259,29 @@ describe("KustoResultTable", () => {

assert.strictEqual(rows.length, 3);
});

describe("test defaultTimespanParser", () => {
it("test nanoseconds", () => {
const actual = new KustoResultTable(v2Response[2]);
const timeParser = actual.timeSpanParser;
const time = timeParser("00:00:00.000000005");
assert.strictEqual(time, 0.000005);
});

it("test complex timespan", () => {
const actual = new KustoResultTable(v2Response[2]);
const timeParser = actual.timeSpanParser;
const time = timeParser("1.02:03:04.0050006");
assert.strictEqual(time, 93784005.0006);
});

it("test negative", () => {
const actual = new KustoResultTable(v2Response[2]);
const timeParser = actual.timeSpanParser;
const time = timeParser("-1.02:03:04.0050006");
// 2 digits precision
assert.strictEqual(time, -93784005.0006);
});
});
});
});
2 changes: 1 addition & 1 deletion packages/azure-kusto-ingest/src/streamUtils.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ export const tryFileToBuffer = async (file: FileDescriptor): Promise<StreamDescr
};

// NOT USED
export const tryStreamToArray = async (stream: any, _maxBufferSize: number): Promise<Buffer> => {
export const tryStreamToArray = async (stream: any): Promise<Buffer> => {
return Promise.resolve(stream);
};
2 changes: 1 addition & 1 deletion packages/quick_start/src/SampleApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ interface ConfigJson {
// TODO (config):
// If this quickstart app was downloaded from OneClick, kusto_sample_config.json should be pre-populated with your cluster's details.
// If this quickstart app was downloaded from GitHub, edit kusto_sample_config.json and modify the cluster URL and database fields appropriately.
const CONFIG_FILE_NAME = "source/kusto_sample_config.json";
const CONFIG_FILE_NAME = "src/kusto_sample_config.json";

class SampleApp {
private static step = 1;
Expand Down

0 comments on commit c487974

Please sign in to comment.