diff --git a/library/sparql/sparql_query_builders.ts b/library/sparql/sparql_query_builders.ts index 2c4bf79..c5b2128 100644 --- a/library/sparql/sparql_query_builders.ts +++ b/library/sparql/sparql_query_builders.ts @@ -1,114 +1,183 @@ import { - build, - createNumericBuilder, - createTemplateBuilder, + braces, + parentheses, + SparqlBuilder, } from "./sparql_shared_builders.ts"; -const OFFSET = createNumericBuilder( - (value) => `OFFSET ${value}\n`, - { build }, -); - -const LIMIT = createNumericBuilder( - (value) => `LIMIT ${value}\n`, - { build, OFFSET }, -); - -const ORDER_BY = createTemplateBuilder( - (value) => `ORDER BY ${value}\n`, - { build, LIMIT }, -); - -const HAVING = createTemplateBuilder( - (value) => `HAVING(${value})\n`, - { build, LIMIT }, -); - -const GROUP_BY = createTemplateBuilder( - (value) => `GROUP BY ${value}\n`, - { build, HAVING, ORDER_BY, LIMIT }, -); - -const WHERE = createTemplateBuilder( - (value) => `WHERE {\n${value}\n}\n`, - { build, GROUP_BY, ORDER_BY, LIMIT }, -); - -const FROM_NAMED = createTemplateBuilder( - (value) => `FROM NAMED ${value}\n`, - { WHERE }, -); - -const FROM = createTemplateBuilder( - (value) => `FROM ${value}\n`, - { FROM_NAMED, WHERE }, -); - -const _SELECT = createTemplateBuilder( - (value) => `SELECT ${value}\n`, - { FROM, FROM_NAMED, WHERE }, -); - -const DISTINCT = createTemplateBuilder( - (value) => `SELECT DISTINCT ${value}\n`, - { FROM, WHERE }, -); - -const REDUCED = createTemplateBuilder( - (value) => `SELECT REDUCED ${value}\n`, - { - FROM, - WHERE, +import { type RDF } from "../rdf.ts"; +import { type SparqlValue } from "./sparql_tag.ts"; + +type Builders = Pick< + SparqlQueryBuilder, + T +>; + +class SparqlQueryBuilder extends SparqlBuilder { + public OFFSET( + number: number, + ): Builders<"build"> { + return this.number(number, "OFFSET"); + } + + public LIMIT( + number: number, + ): Builders<"build" | "OFFSET"> { + return this.number(number, "LIMIT"); + } + + public ORDER_BY( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "LIMIT"> { + return this.template(strings, values, "ORDER BY"); + } + + public HAVING( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "ORDER_BY" | "LIMIT"> { + return this.template(strings, values, "HAVING", parentheses); + } + + public GROUP_BY( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "HAVING" | "ORDER_BY" | "LIMIT"> { + return this.template(strings, values, "GROUP BY"); + } + + public WHERE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "GROUP_BY" | "ORDER_BY" | "LIMIT"> { + return this.template(strings, values, "WHERE", braces); + } + + public FROM_NAMED( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"FROM_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "FROM NAMED"); + } + + public FROM( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"FROM" | "FROM_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "FROM"); + } + + public SELECT( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"FROM" | "FROM_NAMED" | "WHERE"> { + return this.template(strings, values, "SELECT"); + } + + public SELECT_DISTINCT( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"FROM" | "FROM_NAMED" | "WHERE"> { + return this.template(strings, values, "SELECT DISTINCT"); + } + + public SELECT_REDUCED( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"FROM" | "FROM_NAMED" | "WHERE"> { + return this.template(strings, values, "SELECT REDUCED"); + } + + public CONSTRUCT( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"WHERE"> { + return this.template(strings, values, "CONSTRUCT", braces); + } + + public CONSTRUCT_WHERE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "GROUP_BY" | "ORDER_BY" | "LIMIT"> { + return this.template(strings, values, "CONSTRUCT WHERE", braces); + } + + public ASK( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build"> { + return this.template(strings, values, "ASK", braces); + } + + public ASK_FROM( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"FROM" | "FROM_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "ASK\nFROM"); + } + + public ASK_FROM_NAMED( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"FROM_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "ASK\nFROM NAMED"); + } + + public ASK_WHERE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "GROUP_BY" | "ORDER_BY" | "LIMIT"> { + return this.template(strings, values, "ASK\nWHERE", braces); + } + + public DESCRIBE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build" | "FROM" | "FROM_NAMED" | "WHERE"> { + return this.template(strings, values, "DESCRIBE"); + } +} + +export const SELECT = Object.assign(( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlQueryBuilder().SELECT(strings, ...values), { + DISTINCT: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlQueryBuilder().SELECT_DISTINCT(strings, ...values), + REDUCED: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlQueryBuilder().SELECT_REDUCED(strings, ...values), + get ALL() { + return new SparqlQueryBuilder().SELECT`*`; }, -); - -export const SELECT = Object.assign(_SELECT, { - DISTINCT, - REDUCED, - ALL: _SELECT`*`, }); -const _CONSTRUCT = createTemplateBuilder( - (value) => `CONSTRUCT {\n${value}\n}\n`, - { WHERE }, -); - -const _CONSTRUCT_WHERE = createTemplateBuilder( - (value) => `CONSTRUCT WHERE {\n${value}\n}\n`, - { build, GROUP_BY, ORDER_BY, LIMIT }, -); - -export const CONSTRUCT = Object.assign(_CONSTRUCT, { - WHERE: _CONSTRUCT_WHERE, +export const CONSTRUCT = Object.assign(( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlQueryBuilder().CONSTRUCT(strings, ...values), { + WHERE: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlQueryBuilder().CONSTRUCT_WHERE(strings, ...values), }); -const _ASK = createTemplateBuilder( - (value) => `ASK {\n${value}\n}\n`, - { build }, -); - -const _ASK_FROM = createTemplateBuilder( - (value) => `ASK\nFROM ${value}\n`, - { FROM_NAMED, WHERE }, -); - -const _ASK_FROM_NAMED = createTemplateBuilder( - (value) => `ASK\nFROM NAMED ${value}\n`, - { FROM_NAMED, WHERE }, -); - -const _ASK_WHERE = createTemplateBuilder( - (value) => `ASK\nWHERE {\n${value}\n}\n`, - { build, GROUP_BY, ORDER_BY, LIMIT }, -); - -export const ASK = Object.assign(_ASK, { - FROM: _ASK_FROM, - FROM_NAMED: _ASK_FROM_NAMED, - WHERE: _ASK_WHERE, +export const ASK = Object.assign(( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlQueryBuilder().ASK(strings, ...values), { + FROM: ( + stringOrNamedNode: string | RDF.NamedNode, + ) => new SparqlQueryBuilder().ASK_FROM(stringOrNamedNode), + FROM_NAMED: ( + stringOrNamedNode: string | RDF.NamedNode, + ) => new SparqlQueryBuilder().ASK_FROM_NAMED(stringOrNamedNode), + WHERE: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlQueryBuilder().ASK_WHERE(strings, ...values), }); -export const DESCRIBE = createTemplateBuilder( - (value) => `DESCRIBE ${value}\n`, - { build, FROM, FROM_NAMED, WHERE }, -); +export const DESCRIBE = ( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlQueryBuilder().DESCRIBE(strings, ...values); diff --git a/library/sparql/sparql_shared_builders.ts b/library/sparql/sparql_shared_builders.ts index 14b2095..28c6d78 100644 --- a/library/sparql/sparql_shared_builders.ts +++ b/library/sparql/sparql_shared_builders.ts @@ -1,98 +1,60 @@ import { DataFactory, RDF } from "../rdf.ts"; import { sparql, type SparqlValue } from "./sparql_tag.ts"; -type TTemplateBuilder = ( - strings: TemplateStringsArray, - ...values: SparqlValue[] -) => TBuilderCollection; - -type TNumericBuilder = (number: number) => TBuilderCollection; - -type TNamedNodeBuilder = ( - stringOrNamedNode: string | RDF.NamedNode, -) => TBuilderCollection; - -type TTerminalBuilder = () => string; - -type TBuilder = - | TTemplateBuilder - | TNumericBuilder - | TNamedNodeBuilder - | TTerminalBuilder; - -type TBuilderCollection = Record; - -type This = { $partialQuery: string } | undefined; - -const createContext = ( - self: This, - current: string, - builders: TBuilderCollection, -) => { - const previousQuery = self?.$partialQuery || ""; - const context: This = { $partialQuery: previousQuery + current }; - return Object.keys(builders).reduce((acc, key) => { - acc[key] = builders[key].bind(context); - return acc; - }, {} as TBuilderCollection); -}; - -export const createTemplateBuilder = < - TReturnType extends TBuilderCollection, ->( - wrap: (value: string) => string, - builders: TReturnType, -) => { - return function ( - this: unknown, +type Wrap = (keyword: string, value: string) => string; +export const braces: Wrap = (keyword: string, value: string) => + `${keyword} {\n${value}\n}\n`; +export const parentheses: Wrap = (keyword: string, value: string) => + `${keyword} (${value})\n`; +const none: Wrap = (keyword: string, value: string) => `${keyword} ${value}\n`; + +export abstract class SparqlBuilder { + protected value = ""; + protected dataFactory = new DataFactory(); + + public build() { + return this.value; + } + + private sparql( strings: TemplateStringsArray, ...values: SparqlValue[] ) { - const self = (this as This); - const inner = sparql(strings, ...values); - const current = wrap(inner); - return createContext(self, current, builders) as TReturnType; - }; -}; + return !values || values.length < 1 + ? sparql(strings) + : sparql(strings, ...values); + } -export const createNumericBuilder = < - TReturnType extends TBuilderCollection, ->( - wrap: (value: number) => string, - builders: TReturnType, -) => { - return function ( - this: unknown, - number: number, + protected template( + strings: TemplateStringsArray, + values: SparqlValue[], + keyword: string, + wrap: Wrap = none, ) { - const self = (this as This); - const current = wrap(number); - return createContext(self, current, builders) as TReturnType; - }; -}; - -const df = new DataFactory(); - -export const createNamedNodeBuilder = < - TReturnType extends TBuilderCollection, ->( - wrap: (value: string) => string, - builders: TReturnType, -) => { - return function ( - this: unknown, - stringOrNamedNode: string | RDF.NamedNode, + const inputSparql = this.sparql(strings, ...values); + this.value += wrap(keyword, inputSparql); + return this; + } + + protected namedNode( + stringOrNamedNode: string | RDF.NamedNode, + keyword: string, + wrap: Wrap = none, ) { - const self = (this as This); const namedNode = typeof stringOrNamedNode === "string" - ? df.namedNode(stringOrNamedNode) + ? this.dataFactory.namedNode(stringOrNamedNode) : stringOrNamedNode; - const inner = sparql`${namedNode}`; - const current = wrap(inner); - return createContext(self, current, builders) as TReturnType; - }; -}; + const inputSparql = this.sparql`${namedNode}`; + this.value += wrap(keyword, inputSparql); + return this; + } -export const build = function (this: unknown): string { - return (this as This)?.$partialQuery || ""; -}; + protected number( + number: number, + keyword: string, + wrap: Wrap = none, + ) { + this.value += wrap(keyword, number.toString()); + return this; + } +} diff --git a/library/sparql/sparql_update_builders.ts b/library/sparql/sparql_update_builders.ts index a887e80..354e637 100644 --- a/library/sparql/sparql_update_builders.ts +++ b/library/sparql/sparql_update_builders.ts @@ -1,53 +1,88 @@ -import { - build, - createNamedNodeBuilder, - createTemplateBuilder, -} from "./sparql_shared_builders.ts"; - -const WHERE = createTemplateBuilder( - (value) => `WHERE {\n${value}\n}\n`, - { build }, -); - -const USING_NAMED = createNamedNodeBuilder( - (value) => `USING NAMED ${value}\n`, - { WHERE }, -); - -const USING = createNamedNodeBuilder( - (value) => `USING ${value}\n`, - { USING_NAMED, WHERE }, -); - -const _INSERT = createTemplateBuilder( - (value) => `INSERT {\n${value}\n}\n`, - { USING, USING_NAMED, WHERE }, -); - -const _INSERT_DATA = createTemplateBuilder( - (value) => `INSERT DATA {\n${value}\n}\n`, - { build }, -); - -export const INSERT = Object.assign(_INSERT, { - DATA: _INSERT_DATA, -}); +import { braces, SparqlBuilder } from "./sparql_shared_builders.ts"; + +import { type RDF } from "../rdf.ts"; +import { type SparqlValue } from "./sparql_tag.ts"; + +type Builders = Pick< + SparqlUpdateBuilder, + T +>; + +class SparqlUpdateBuilder extends SparqlBuilder { + public WHERE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build"> { + return this.template(strings, values, "WHERE", braces); + } + + public USING_NAMED( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"USING_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "USING NAMED"); + } + + public USING( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"USING" | "USING_NAMED" | "WHERE"> { + return this.namedNode(stringOrNamedNode, "USING"); + } -const _DELETE = createTemplateBuilder( - (value) => `DELETE {\n${value}\n}\n`, - { INSERT: _INSERT, USING, USING_NAMED, WHERE }, -); + public INSERT( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"USING" | "USING_NAMED" | "WHERE"> { + return this.template(strings, values, "INSERT", braces); + } -const _DELETE_DATA = createTemplateBuilder( - (value) => `DELETE DATA {\n${value}\n}\n`, - { build }, -); + public INSERT_DATA( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build"> { + return this.template(strings, values, "INSERT DATA", braces); + } + + public DELETE( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"INSERT" | "USING" | "USING_NAMED" | "WHERE"> { + return this.template(strings, values, "DELETE", braces); + } + + public DELETE_DATA( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ): Builders<"build"> { + return this.template(strings, values, "DELETE DATA", braces); + } + + public WITH( + stringOrNamedNode: string | RDF.NamedNode, + ): Builders<"INSERT" | "DELETE"> { + return this.namedNode(stringOrNamedNode, "WITH"); + } +} + +export const INSERT = Object.assign(( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlUpdateBuilder().INSERT(strings, ...values), { + DATA: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlUpdateBuilder().INSERT_DATA(strings, ...values), +}); -export const DELETE = Object.assign(_DELETE, { - DATA: _DELETE_DATA, +export const DELETE = Object.assign(( + strings: TemplateStringsArray, + ...values: SparqlValue[] +) => new SparqlUpdateBuilder().DELETE(strings, ...values), { + DATA: ( + strings: TemplateStringsArray, + ...values: SparqlValue[] + ) => new SparqlUpdateBuilder().DELETE_DATA(strings, ...values), }); -export const WITH = createNamedNodeBuilder( - (value) => `WITH ${value}\n`, - { build, INSERT: _INSERT, DELETE: _DELETE }, -); +export const WITH = ( + stringOrNamedNode: string | RDF.NamedNode, +) => new SparqlUpdateBuilder().WITH(stringOrNamedNode); diff --git a/specs/sparql_query_builders.test.ts b/specs/sparql_query_builders.test.ts index 5b467d7..24fe54d 100644 --- a/specs/sparql_query_builders.test.ts +++ b/specs/sparql_query_builders.test.ts @@ -45,14 +45,14 @@ Deno.test("SPARQL / Sparql builder SELECT #4", () => { Deno.test("SPARQL / Sparql builder SELECT #5", () => { const expected = "SELECT ?s\nFROM \nWHERE {\n?s ?p ?o .\n}\n"; - const query = SELECT`${s}`.FROM`${g}`.WHERE`${spo}`.build(); + const query = SELECT`${s}`.FROM(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); Deno.test("SPARQL / Sparql builder SELECT #6", () => { const expected = "SELECT ?s\nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = SELECT`${s}`.FROM_NAMED`${g}`.WHERE`${spo}`.build(); + const query = SELECT`${s}`.FROM_NAMED(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); @@ -60,7 +60,7 @@ Deno.test("SPARQL / Sparql builder SELECT #6", () => { Deno.test("SPARQL / Sparql builder SELECT #7", () => { const expected = "SELECT ?s\nFROM \nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = SELECT`${s}`.FROM`${g}`.FROM_NAMED`${g}`.WHERE`${spo}`.build(); + const query = SELECT`${s}`.FROM(g).FROM_NAMED(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); @@ -106,7 +106,7 @@ Deno.test("SPARQL / Sparql builder SELECT #12", () => { Deno.test("SPARQL / Sparql builder SELECT #13", () => { const expected = - "SELECT ?s\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING(true)\n"; + "SELECT ?s\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING (true)\n"; const query = SELECT`${s}`.WHERE`${spo}`.GROUP_BY`${s}`.HAVING`${true}` .build(); @@ -115,7 +115,7 @@ Deno.test("SPARQL / Sparql builder SELECT #13", () => { Deno.test("SPARQL / Sparql builder SELECT #14", () => { const expected = - "SELECT ?s\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING(true)\nLIMIT 5\n"; + "SELECT ?s\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING (true)\nLIMIT 5\n"; const query = SELECT`${s}`.WHERE`${spo}`.GROUP_BY`${s}`.HAVING`${true}` .LIMIT(5) .build(); @@ -123,6 +123,13 @@ Deno.test("SPARQL / Sparql builder SELECT #14", () => { assertEquals(query, expected); }); +Deno.test("SPARQL / Sparql builder SELECT #15", () => { + const expected = "SELECT ?x ?s ?y\nWHERE {\n?s ?p ?o .\n?s ?p ?o .\n}\n"; + const query = SELECT`?x ${s} ?y`.WHERE`${[spo, spo]}`.build(); + + assertEquals(query, expected); +}); + Deno.test("SPARQL / Sparql builder CONSTRUCT #1", () => { const expected = "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\n"; const query = CONSTRUCT`${spo}`.WHERE`${spo}`.build(); @@ -184,7 +191,7 @@ Deno.test("SPARQL / Sparql builder CONSTRUCT #7", () => { Deno.test("SPARQL / Sparql builder CONSTRUCT #8", () => { const expected = - "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING(true)\n"; + "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING (true)\n"; const query = CONSTRUCT`${spo}`.WHERE`${spo}`.GROUP_BY`${s}`.HAVING`${true}` .build(); @@ -193,7 +200,7 @@ Deno.test("SPARQL / Sparql builder CONSTRUCT #8", () => { Deno.test("SPARQL / Sparql builder CONSTRUCT #9", () => { const expected = - "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING(true)\nLIMIT 5\n"; + "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING (true)\nLIMIT 5\n"; const query = CONSTRUCT`${spo}`.WHERE`${spo}`.GROUP_BY`${s}`.HAVING`${true}` .LIMIT(5) .build(); @@ -203,7 +210,7 @@ Deno.test("SPARQL / Sparql builder CONSTRUCT #9", () => { Deno.test("SPARQL / Sparql builder CONSTRUCT #10", () => { const expected = - "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING(true)\nLIMIT 5\n"; + "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\nGROUP BY ?s\nHAVING (true)\nLIMIT 5\n"; const query = CONSTRUCT`${spo}`.WHERE`${spo}`.GROUP_BY`${s}`.HAVING`${true}` .LIMIT(5) .build(); @@ -211,6 +218,15 @@ Deno.test("SPARQL / Sparql builder CONSTRUCT #10", () => { assertEquals(query, expected); }); +Deno.test("SPARQL / Sparql builder CONSTRUCT #11", () => { + const expected = + "CONSTRUCT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\nVALUES ?s { }\n}\n"; + const query = CONSTRUCT`${spo}` + .WHERE`${spo}\nVALUES ?s { ${[df.namedNode("x")]} }`.build(); + + assertEquals(query, expected); +}); + Deno.test("SPARQL / Sparql builder ASK #1", () => { const expected = "ASK {\n?s ?p ?o .\n}\n"; const query = ASK`${spo}`.build(); @@ -227,21 +243,21 @@ Deno.test("SPARQL / Sparql builder ASK #2", () => { Deno.test("SPARQL / Sparql builder ASK #3", () => { const expected = "ASK\nFROM \nWHERE {\n?s ?p ?o .\n}\n"; - const query = ASK.FROM`${g}`.WHERE`${spo}`.build(); + const query = ASK.FROM(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); Deno.test("SPARQL / Sparql builder ASK #4", () => { const expected = "ASK\nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = ASK.FROM_NAMED`${g}`.WHERE`${spo}`.build(); + const query = ASK.FROM_NAMED(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); Deno.test("SPARQL / Sparql builder ASK #5", () => { const expected = "ASK\nFROM \nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = ASK.FROM`${g}`.FROM_NAMED`${g}`.WHERE`${spo}`.build(); + const query = ASK.FROM(g).FROM_NAMED(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); @@ -262,14 +278,14 @@ Deno.test("SPARQL / Sparql builder DESCRIBE #2", () => { Deno.test("SPARQL / Sparql builder DESCRIBE #3", () => { const expected = "DESCRIBE \nFROM \nWHERE {\n?s ?p ?o .\n}\n"; - const query = DESCRIBE`${g}`.FROM`${g}`.WHERE`${spo}`.build(); + const query = DESCRIBE`${g}`.FROM(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); Deno.test("SPARQL / Sparql builder DESCRIBE #4", () => { const expected = "DESCRIBE \nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = DESCRIBE`${g}`.FROM_NAMED`${g}`.WHERE`${spo}`.build(); + const query = DESCRIBE`${g}`.FROM_NAMED(g).WHERE`${spo}`.build(); assertEquals(query, expected); }); @@ -277,7 +293,7 @@ Deno.test("SPARQL / Sparql builder DESCRIBE #4", () => { Deno.test("SPARQL / Sparql builder DESCRIBE #5", () => { const expected = "DESCRIBE \nFROM \nFROM NAMED \nWHERE {\n?s ?p ?o .\n}\n"; - const query = DESCRIBE`${g}`.FROM`${g}`.FROM_NAMED`${g}`.WHERE`${spo}` + const query = DESCRIBE`${g}`.FROM(g).FROM_NAMED(g).WHERE`${spo}` .build(); assertEquals(query, expected); diff --git a/specs/sparql_tag.test.ts b/specs/sparql_tag.test.ts index 38a3ee3..5f26783 100644 --- a/specs/sparql_tag.test.ts +++ b/specs/sparql_tag.test.ts @@ -6,9 +6,12 @@ import xsd from "../library/namespaces/xsd.ts"; const df = new DataFactory(); -Deno.test("SPARQL / Sparql tag basic types", () => { +Deno.test("SPARQL / Sparql tags simple strings", () => { assertEquals(sparql``, ""); + assertEquals(sparql`abc`, "abc"); +}); +Deno.test("SPARQL / Sparql tag basic types", () => { assertEquals(sparql`${df.blankNode("x")}`, "_:x"); assertEquals(sparql`${df.namedNode("x")}`, ""); assertEquals(sparql`${df.variable("x")}`, "?x"); diff --git a/specs/sparql_update_builders.test.ts b/specs/sparql_update_builders.test.ts index 707b596..5baf804 100644 --- a/specs/sparql_update_builders.test.ts +++ b/specs/sparql_update_builders.test.ts @@ -44,6 +44,15 @@ Deno.test("SPARQL / Sparql builder INSERT #4", () => { assertEquals(query, expected); }); +Deno.test("SPARQL / Sparql builder INSERT #5", () => { + const expected = + "INSERT {\n?s ?p ?o .\n}\nUSING \nUSING \nUSING NAMED \nUSING NAMED \nUSING NAMED \nWHERE {\n?s ?p ?o .\n}\n"; + const query = INSERT`${spo}`.USING("g").USING("g").USING_NAMED(g) + .USING_NAMED(g).USING_NAMED(g).WHERE`${spo}`.build(); + + assertEquals(query, expected); +}); + Deno.test("SPARQL / Sparql builder DELETE #1", () => { const expected = "DELETE DATA {\n?s ?p ?o .\n}\n"; const query = DELETE.DATA`${spo}`.build(); @@ -83,6 +92,23 @@ Deno.test("SPARQL / Sparql builder DELETE #5", () => { assertEquals(query, expected); }); +Deno.test("SPARQL / Sparql builder DELETE #6", () => { + const expected = + "DELETE {\n?s ?p ?o .\n}\nINSERT {\n?s ?p ?o .\n}\nUSING \nUSING \nUSING NAMED \nUSING NAMED \nUSING NAMED \nWHERE {\n?s ?p ?o .\n}\n"; + const query = DELETE`${spo}`.INSERT`${spo}`.USING("g").USING("g") + .USING_NAMED(g).USING_NAMED(g).USING_NAMED(g) + .WHERE`${spo}`.build(); + + assertEquals(query, expected); +}); + +Deno.test("SPARQL / Sparql builder DELETE #7", () => { + const expected = "DELETE {\n?s ?p ?o\n}\nWHERE {\n?s ?p ?o\n}\n"; + const query = DELETE`?s ?p ?o`.WHERE`?s ?p ?o`.build(); + + assertEquals(query, expected); +}); + Deno.test("SPARQL / Sparql builder WITH #1", () => { const expected = "WITH \nDELETE {\n?s ?p ?o .\n}\nINSERT {\n?s ?p ?o .\n}\nWHERE {\n?s ?p ?o .\n}\n";