Skip to content

Commit 95c005d

Browse files
committed
cloneColumnWithOffset new options offset and categories
1 parent 6c37710 commit 95c005d

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

src/class/SimpleTable.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -725,23 +725,60 @@ export default class SimpleTable extends Simple {
725725
}
726726

727727
/**
728-
* Clones a column in the table and offsets the values down by one row. The last row will have a NULL value.
728+
* Clones a column in the table and offsets the values. By default, the values are offset by 1.
729729
*
730730
* @example
731731
* Basic usage
732732
* ```ts
733733
* // Clones column1 as column2 and offsets values by 1. So value of column1-row1 will be in column2-row2, column1-row2 will be in column2-row3, etc.
734734
* await table.cloneColumnWithOffset("column1", "column2")
735735
* ```
736+
*
737+
* @example
738+
* With specific offset
739+
* ```ts
740+
* // Clones column1 as column2 and offsets values by 2. So value of column1-row1 will be in column2-row3, column1-row2 will be in column2-row4, etc.
741+
* await table.cloneColumnWithOffset("column1", "column2", { offset: 2 })
742+
* ```
743+
*
744+
* @example
745+
* With categories
746+
* ```ts
747+
* // The offset is done within the categories category1 and category2.
748+
* await table.cloneColumnWithOffset("column1", "column2", { offset: 2, categories: ["category1", "category2"] })
749+
* ```
750+
*
736751
* @param originalColumn - The original column.
737752
* @param newColumn - The name of the cloned column.
753+
* @param options - An optional object with configuration options:
754+
* @param options.offset - The number of rows to offset the values. Defaults to 1.
755+
* @param options.categories - A string or an array of strings representing the categories.
738756
*
739757
* @category Restructuring data
740758
*/
741-
async cloneColumnWithOffset(originalColumn: string, newColumn: string) {
759+
async cloneColumnWithOffset(
760+
originalColumn: string,
761+
newColumn: string,
762+
options: {
763+
offset?: number;
764+
categories?: string | string[];
765+
} = {},
766+
) {
767+
const offset = options.offset ?? 1;
768+
const categories = options.categories
769+
? stringToArray(options.categories)
770+
: [];
771+
const partition = categories.length > 0
772+
? `PARTITION BY ${categories.map((d) => `"${d}"`).join(", ")}`
773+
: "";
774+
742775
await queryDB(
743776
this,
744-
`CREATE OR REPLACE TABLE "${this.name}" AS SELECT *, LEAD(${originalColumn}) OVER() AS ${newColumn} FROM "${this.name}"`,
777+
`CREATE OR REPLACE TABLE "${this.name}" AS SELECT *, LEAD("${originalColumn}", ${offset}) OVER(${partition}) AS "${newColumn}" FROM "${this.name}"${
778+
categories.length > 0
779+
? ` ORDER BY ${categories.map((d) => `"${d}"`).join(", ")}`
780+
: ""
781+
};`,
745782
mergeOptions(this, {
746783
table: this.name,
747784
method: "cloneColumnWithOffset()",

test/unit/methods/cloneColumnWithOffset.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,80 @@ Deno.test("should clone a column with an offset", async () => {
2828

2929
await sdb.done();
3030
});
31+
Deno.test("should clone a column with an offset of 2", async () => {
32+
const sdb = new SimpleDB();
33+
const table = sdb.newTable("data");
34+
await table.loadArray([
35+
{ firstName: "nael", lastName: "shiab" },
36+
{ firstName: "graeme", lastName: "bruce" },
37+
{ firstName: "wendy", lastName: "martinez" },
38+
{ firstName: "andrew", lastName: "ryan" },
39+
]);
40+
41+
await table.cloneColumnWithOffset("firstName", "nextFirstName", {
42+
offset: 2,
43+
});
3144

45+
const data = await table.getData();
46+
47+
assertEquals(data, [
48+
{ firstName: "nael", lastName: "shiab", nextFirstName: "wendy" },
49+
{ firstName: "graeme", lastName: "bruce", nextFirstName: "andrew" },
50+
{
51+
firstName: "wendy",
52+
lastName: "martinez",
53+
nextFirstName: null,
54+
},
55+
{ firstName: "andrew", lastName: "ryan", nextFirstName: null },
56+
]);
57+
58+
await sdb.done();
59+
});
60+
Deno.test("should clone a column with a category", async () => {
61+
const sdb = new SimpleDB();
62+
const table = sdb.newTable("data");
63+
await table.loadArray([
64+
{ group: "A", firstName: "nael", lastName: "shiab" },
65+
{ group: "B", firstName: "wendy", lastName: "martinez" },
66+
{ group: "A", firstName: "graeme", lastName: "bruce" },
67+
{ group: "B", firstName: "andrew", lastName: "ryan" },
68+
]);
69+
70+
await table.cloneColumnWithOffset("firstName", "nextFirstName", {
71+
categories: "group",
72+
});
73+
74+
const data = await table.getData();
75+
76+
assertEquals(data, [
77+
{
78+
group: "A",
79+
firstName: "nael",
80+
lastName: "shiab",
81+
nextFirstName: "graeme",
82+
},
83+
{
84+
group: "A",
85+
firstName: "graeme",
86+
lastName: "bruce",
87+
nextFirstName: null,
88+
},
89+
{
90+
group: "B",
91+
firstName: "wendy",
92+
lastName: "martinez",
93+
nextFirstName: "andrew",
94+
},
95+
{
96+
group: "B",
97+
firstName: "andrew",
98+
lastName: "ryan",
99+
nextFirstName: null,
100+
},
101+
]);
102+
103+
await sdb.done();
104+
});
32105
Deno.test("should clone a column with an offset when working with geometries and keep the projection", async () => {
33106
const sdb = new SimpleDB();
34107
const table = sdb.newTable("data");

0 commit comments

Comments
 (0)