@superblocksteam/sdk-api 2.0.104-next.0 → 2.0.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/integrations/athena/types.d.ts +2 -2
- package/dist/integrations/bigquery/types.d.ts +3 -3
- package/dist/integrations/databricks/types.d.ts +3 -3
- package/dist/integrations/documentation.test.d.ts +2 -0
- package/dist/integrations/documentation.test.d.ts.map +1 -0
- package/dist/integrations/documentation.test.js +83 -0
- package/dist/integrations/documentation.test.js.map +1 -0
- package/dist/integrations/lakebase/types.d.ts +4 -4
- package/dist/integrations/mariadb/types.d.ts +2 -2
- package/dist/integrations/mssql/types.d.ts +2 -2
- package/dist/integrations/mysql/types.d.ts +4 -4
- package/dist/integrations/oracledb/types.d.ts +2 -2
- package/package.json +1 -1
- package/src/integrations/athena/README.md +4 -4
- package/src/integrations/athena/types.ts +2 -2
- package/src/integrations/bigquery/README.md +28 -3
- package/src/integrations/bigquery/types.ts +3 -3
- package/src/integrations/databricks/README.md +29 -4
- package/src/integrations/databricks/types.ts +3 -3
- package/src/integrations/documentation.test.ts +122 -0
- package/src/integrations/lakebase/types.ts +4 -4
- package/src/integrations/mariadb/README.md +3 -3
- package/src/integrations/mariadb/types.ts +2 -2
- package/src/integrations/mssql/README.md +3 -3
- package/src/integrations/mssql/types.ts +2 -2
- package/src/integrations/mysql/README.md +4 -4
- package/src/integrations/mysql/types.ts +4 -4
- package/src/integrations/oracledb/README.md +3 -3
- package/src/integrations/oracledb/types.ts +2 -2
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const logs = await athena.query(
|
|
25
|
-
* 'SELECT * FROM logs WHERE level =
|
|
25
|
+
* 'SELECT * FROM logs WHERE level = ?',
|
|
26
26
|
* LogSchema,
|
|
27
27
|
* ['ERROR']
|
|
28
28
|
* );
|
|
@@ -32,7 +32,7 @@ export interface AthenaClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
37
|
* @param params - Optional query parameters
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const events = await bigquery.query(
|
|
25
|
-
* 'SELECT * FROM events WHERE date =
|
|
25
|
+
* 'SELECT * FROM events WHERE date = ?',
|
|
26
26
|
* EventSchema,
|
|
27
27
|
* ['2024-01-01']
|
|
28
28
|
* );
|
|
@@ -32,9 +32,9 @@ export interface BigQueryClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
|
-
* @param params - Optional query parameters
|
|
37
|
+
* @param params - Optional query parameters, bound positionally from the provided array
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
39
39
|
*
|
|
40
40
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const data = await databricks.query(
|
|
25
|
-
* 'SELECT * FROM data WHERE date =
|
|
25
|
+
* 'SELECT * FROM data WHERE date = :PARAM_1',
|
|
26
26
|
* DataSchema,
|
|
27
27
|
* ['2024-01-01']
|
|
28
28
|
* );
|
|
@@ -32,9 +32,9 @@ export interface DatabricksClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use :PARAM_1, :PARAM_2, etc. for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
|
-
* @param params - Optional query parameters
|
|
37
|
+
* @param params - Optional query parameters, bound positionally so the first value maps to :PARAM_1
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
39
39
|
*
|
|
40
40
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentation.test.d.ts","sourceRoot":"","sources":["../../src/integrations/documentation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { SUPPORTED_PLUGINS } from "./registry.js";
|
|
6
|
+
const TEST_DIR = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const DOC_DIRECTORY_ALIASES = {
|
|
8
|
+
confluent: "kafka",
|
|
9
|
+
graphqlintegration: "graphql",
|
|
10
|
+
redpanda: "kafka",
|
|
11
|
+
};
|
|
12
|
+
const DOC_DIRECTORY_EXCLUSIONS = new Set(["base"]);
|
|
13
|
+
function hasDocDirectoryAlias(pluginId) {
|
|
14
|
+
return pluginId in DOC_DIRECTORY_ALIASES;
|
|
15
|
+
}
|
|
16
|
+
const EXPECTED_DOC_DIRECTORIES = Array.from(new Set(Object.values(SUPPORTED_PLUGINS)
|
|
17
|
+
.map((pluginId) => hasDocDirectoryAlias(pluginId)
|
|
18
|
+
? DOC_DIRECTORY_ALIASES[pluginId]
|
|
19
|
+
: pluginId)
|
|
20
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory)))).sort();
|
|
21
|
+
const ACTUAL_DOC_DIRECTORIES = readdirSync(TEST_DIR, { withFileTypes: true })
|
|
22
|
+
.filter((entry) => entry.isDirectory())
|
|
23
|
+
.map((entry) => entry.name)
|
|
24
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory))
|
|
25
|
+
.sort();
|
|
26
|
+
const PLACEHOLDER_DOC_CASES = [
|
|
27
|
+
{ integrationId: "athena", expectedPlaceholder: "?" },
|
|
28
|
+
{ integrationId: "bigquery", expectedPlaceholder: "?" },
|
|
29
|
+
{
|
|
30
|
+
integrationId: "cockroachdb",
|
|
31
|
+
expectedPlaceholder: "$1",
|
|
32
|
+
rejectsPostgresStyle: false,
|
|
33
|
+
},
|
|
34
|
+
{ integrationId: "databricks", expectedPlaceholder: ":PARAM_1" },
|
|
35
|
+
{ integrationId: "dynamodb", expectedPlaceholder: "?" },
|
|
36
|
+
{
|
|
37
|
+
integrationId: "lakebase",
|
|
38
|
+
expectedPlaceholder: "$1",
|
|
39
|
+
rejectsPostgresStyle: false,
|
|
40
|
+
},
|
|
41
|
+
{ integrationId: "mariadb", expectedPlaceholder: "?" },
|
|
42
|
+
{ integrationId: "mssql", expectedPlaceholder: "@PARAM_1" },
|
|
43
|
+
{ integrationId: "mysql", expectedPlaceholder: "?" },
|
|
44
|
+
{ integrationId: "oracledb", expectedPlaceholder: ":1" },
|
|
45
|
+
{
|
|
46
|
+
integrationId: "redshift",
|
|
47
|
+
expectedPlaceholder: "$1",
|
|
48
|
+
rejectsPostgresStyle: false,
|
|
49
|
+
},
|
|
50
|
+
{ integrationId: "snowflake", expectedPlaceholder: "?" },
|
|
51
|
+
{
|
|
52
|
+
integrationId: "snowflakepostgres",
|
|
53
|
+
expectedPlaceholder: "$1",
|
|
54
|
+
rejectsPostgresStyle: false,
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
function readIntegrationFile(integrationId, fileName) {
|
|
58
|
+
return readFileSync(resolve(TEST_DIR, integrationId, fileName), "utf8");
|
|
59
|
+
}
|
|
60
|
+
describe("SQL integration documentation", () => {
|
|
61
|
+
it("documents every supported integration directory", () => {
|
|
62
|
+
expect(ACTUAL_DOC_DIRECTORIES).toEqual(EXPECTED_DOC_DIRECTORIES);
|
|
63
|
+
for (const integrationId of EXPECTED_DOC_DIRECTORIES) {
|
|
64
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "README.md"))).toBe(true);
|
|
65
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "types.ts"))).toBe(true);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
it.each(PLACEHOLDER_DOC_CASES)("$integrationId README uses $expectedPlaceholder placeholders", ({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
69
|
+
const readme = readIntegrationFile(integrationId, "README.md");
|
|
70
|
+
expect(readme).toContain(expectedPlaceholder);
|
|
71
|
+
if (rejectsPostgresStyle) {
|
|
72
|
+
expect(readme).not.toMatch(/\$\d+/);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
it.each(PLACEHOLDER_DOC_CASES)("$integrationId JSDoc uses $expectedPlaceholder placeholders", ({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
76
|
+
const typeDocs = readIntegrationFile(integrationId, "types.ts");
|
|
77
|
+
expect(typeDocs).toContain(expectedPlaceholder);
|
|
78
|
+
if (rejectsPostgresStyle) {
|
|
79
|
+
expect(typeDocs).not.toMatch(/\$\d+/);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=documentation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentation.test.js","sourceRoot":"","sources":["../../src/integrations/documentation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,14 +16,14 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
16
16
|
*
|
|
17
17
|
* // Parameterized query
|
|
18
18
|
* const users = await lb.query(
|
|
19
|
-
* 'SELECT * FROM users WHERE status =
|
|
19
|
+
* 'SELECT * FROM users WHERE status = $1',
|
|
20
20
|
* UserSchema,
|
|
21
21
|
* ['active'],
|
|
22
22
|
* );
|
|
23
23
|
*
|
|
24
24
|
* // Execute a mutation
|
|
25
25
|
* const result = await lb.execute(
|
|
26
|
-
* 'INSERT INTO users (name, email) VALUES (
|
|
26
|
+
* 'INSERT INTO users (name, email) VALUES ($1, $2)',
|
|
27
27
|
* ['Alice', 'alice@example.com'],
|
|
28
28
|
* );
|
|
29
29
|
* ```
|
|
@@ -32,7 +32,7 @@ export interface LakebaseClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and return validated rows.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string with
|
|
35
|
+
* @param sql - SQL query string with `$1`, `$2` placeholders for parameters
|
|
36
36
|
* @param schema - Zod schema for validating each result row
|
|
37
37
|
* @param params - Optional query parameters for server-side binding
|
|
38
38
|
* @returns Array of validated rows
|
|
@@ -41,7 +41,7 @@ export interface LakebaseClient extends BaseIntegrationClient {
|
|
|
41
41
|
/**
|
|
42
42
|
* Execute a SQL statement (INSERT, UPDATE, DELETE).
|
|
43
43
|
*
|
|
44
|
-
* @param sql - SQL statement with
|
|
44
|
+
* @param sql - SQL statement with `$1`, `$2` placeholders for parameters
|
|
45
45
|
* @param params - Optional query parameters for server-side binding
|
|
46
46
|
* @returns The affected row count
|
|
47
47
|
*/
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const users = await mariadb.query(
|
|
25
|
-
* 'SELECT * FROM users WHERE status =
|
|
25
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
26
26
|
* UserSchema,
|
|
27
27
|
* ['active']
|
|
28
28
|
* );
|
|
@@ -32,7 +32,7 @@ export interface MariaDBClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
37
|
* @param params - Optional query parameters
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const users = await mssql.query(
|
|
25
|
-
* 'SELECT * FROM users WHERE status =
|
|
25
|
+
* 'SELECT * FROM users WHERE status = @PARAM_1',
|
|
26
26
|
* UserSchema,
|
|
27
27
|
* ['active']
|
|
28
28
|
* );
|
|
@@ -32,7 +32,7 @@ export interface MSSQLClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use @PARAM_1, @PARAM_2, etc. for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
37
|
* @param params - Optional query parameters
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const users = await mysql.query(
|
|
25
|
-
* 'SELECT * FROM users WHERE status =
|
|
25
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
26
26
|
* UserSchema,
|
|
27
27
|
* ['active']
|
|
28
28
|
* );
|
|
@@ -32,7 +32,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
37
|
* @param params - Optional query parameters
|
|
38
38
|
* @returns Promise resolving to validated query results
|
|
@@ -49,7 +49,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
49
49
|
* });
|
|
50
50
|
*
|
|
51
51
|
* const users = await mysql.query(
|
|
52
|
-
* 'SELECT * FROM users WHERE status =
|
|
52
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
53
53
|
* UserSchema,
|
|
54
54
|
* ['active']
|
|
55
55
|
* );
|
|
@@ -66,7 +66,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
66
66
|
* @example
|
|
67
67
|
* ```typescript
|
|
68
68
|
* const result = await mysql.execute(
|
|
69
|
-
* 'UPDATE users SET last_login = NOW() WHERE id =
|
|
69
|
+
* 'UPDATE users SET last_login = NOW() WHERE id = ?',
|
|
70
70
|
* [userId]
|
|
71
71
|
* );
|
|
72
72
|
* console.log(`Updated ${result.rowCount} rows`);
|
|
@@ -22,7 +22,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
22
22
|
* });
|
|
23
23
|
*
|
|
24
24
|
* const users = await oracledb.query(
|
|
25
|
-
* 'SELECT * FROM users WHERE status =
|
|
25
|
+
* 'SELECT * FROM users WHERE status = :1',
|
|
26
26
|
* UserSchema,
|
|
27
27
|
* ['active']
|
|
28
28
|
* );
|
|
@@ -32,7 +32,7 @@ export interface OracleDBClient extends BaseIntegrationClient {
|
|
|
32
32
|
/**
|
|
33
33
|
* Execute a SQL query and validate results against a Zod schema.
|
|
34
34
|
*
|
|
35
|
-
* @param sql - SQL query string (use
|
|
35
|
+
* @param sql - SQL query string (use :1, :2, etc. for parameters)
|
|
36
36
|
* @param schema - Zod schema to validate the query results
|
|
37
37
|
* @param params - Optional query parameters
|
|
38
38
|
* @returns Promise resolving to validated query results
|
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@ export default api({
|
|
|
41
41
|
const logs = await ctx.integrations.athena.query(
|
|
42
42
|
`SELECT timestamp, level, message, request_id
|
|
43
43
|
FROM logs
|
|
44
|
-
WHERE level =
|
|
44
|
+
WHERE level = ?
|
|
45
45
|
LIMIT 100`,
|
|
46
46
|
LogSchema,
|
|
47
47
|
[level],
|
|
@@ -65,8 +65,8 @@ const EventSchema = z.object({
|
|
|
65
65
|
const events = await ctx.integrations.athena.query(
|
|
66
66
|
`SELECT event_id, event_type, user_id, created_at
|
|
67
67
|
FROM events
|
|
68
|
-
WHERE date_partition =
|
|
69
|
-
AND event_type =
|
|
68
|
+
WHERE date_partition = ?
|
|
69
|
+
AND event_type = ?`,
|
|
70
70
|
EventSchema,
|
|
71
71
|
["2024-01-15", "purchase"],
|
|
72
72
|
);
|
|
@@ -138,7 +138,7 @@ Always use partition filters when possible to reduce data scanned:
|
|
|
138
138
|
```typescript
|
|
139
139
|
// GOOD - Uses partition filter
|
|
140
140
|
const logs = await ctx.integrations.athena.query(
|
|
141
|
-
"SELECT * FROM logs WHERE date_partition =
|
|
141
|
+
"SELECT * FROM logs WHERE date_partition = ?",
|
|
142
142
|
LogSchema,
|
|
143
143
|
["2024-01-15"],
|
|
144
144
|
);
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const logs = await athena.query(
|
|
28
|
-
* 'SELECT * FROM logs WHERE level =
|
|
28
|
+
* 'SELECT * FROM logs WHERE level = ?',
|
|
29
29
|
* LogSchema,
|
|
30
30
|
* ['ERROR']
|
|
31
31
|
* );
|
|
@@ -35,7 +35,7 @@ export interface AthenaClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
40
|
* @param params - Optional query parameters
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
@@ -40,7 +40,7 @@ export default api({
|
|
|
40
40
|
const events = await ctx.integrations.bigquery.query(
|
|
41
41
|
`SELECT event_id, event_name, user_id, timestamp
|
|
42
42
|
FROM \`project.dataset.events\`
|
|
43
|
-
WHERE event_name =
|
|
43
|
+
WHERE event_name = ?
|
|
44
44
|
LIMIT 100`,
|
|
45
45
|
EventSchema,
|
|
46
46
|
[event_name],
|
|
@@ -51,12 +51,16 @@ export default api({
|
|
|
51
51
|
});
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
The SDK currently binds BigQuery parameters from the positional `params` array.
|
|
55
|
+
Even though native BigQuery also supports named parameters like `@event_name`,
|
|
56
|
+
use `?` placeholders in SDK queries and pass values in array order.
|
|
57
|
+
|
|
54
58
|
### Executing INSERT, UPDATE, DELETE Statements
|
|
55
59
|
|
|
56
60
|
```typescript
|
|
57
61
|
// INSERT
|
|
58
62
|
await ctx.integrations.bigquery.execute(
|
|
59
|
-
"INSERT INTO `project.dataset.metrics` (name, value, timestamp) VALUES (
|
|
63
|
+
"INSERT INTO `project.dataset.metrics` (name, value, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP())",
|
|
60
64
|
["cpu_usage", "75.5"],
|
|
61
65
|
);
|
|
62
66
|
```
|
|
@@ -116,6 +120,27 @@ All methods accept an optional `metadata` parameter as the last argument for dia
|
|
|
116
120
|
|
|
117
121
|
## Common Pitfalls
|
|
118
122
|
|
|
123
|
+
### SDK Parameters Are Positional
|
|
124
|
+
|
|
125
|
+
The SDK accepts an array of parameter values and binds them server-side in
|
|
126
|
+
order. When you need parameters, use `?` placeholders in the SQL text:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
// WRONG - Native BigQuery named parameter syntax is not the SDK contract
|
|
130
|
+
await ctx.integrations.bigquery.query(
|
|
131
|
+
"SELECT * FROM `project.dataset.events` WHERE event_name = @event_name",
|
|
132
|
+
EventSchema,
|
|
133
|
+
["signup"],
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// CORRECT - Use positional params with ? placeholders
|
|
137
|
+
await ctx.integrations.bigquery.query(
|
|
138
|
+
"SELECT * FROM `project.dataset.events` WHERE event_name = ?",
|
|
139
|
+
EventSchema,
|
|
140
|
+
["signup"],
|
|
141
|
+
);
|
|
142
|
+
```
|
|
143
|
+
|
|
119
144
|
### Backtick Table References
|
|
120
145
|
|
|
121
146
|
BigQuery uses backticks for fully-qualified table names:
|
|
@@ -165,7 +190,7 @@ BigQuery charges by data scanned. Use partitions and column selection:
|
|
|
165
190
|
const query = `
|
|
166
191
|
SELECT event_id, event_name
|
|
167
192
|
FROM \`project.dataset.events\`
|
|
168
|
-
WHERE _PARTITIONDATE =
|
|
193
|
+
WHERE _PARTITIONDATE = ?
|
|
169
194
|
`;
|
|
170
195
|
```
|
|
171
196
|
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const events = await bigquery.query(
|
|
28
|
-
* 'SELECT * FROM events WHERE date =
|
|
28
|
+
* 'SELECT * FROM events WHERE date = ?',
|
|
29
29
|
* EventSchema,
|
|
30
30
|
* ['2024-01-01']
|
|
31
31
|
* );
|
|
@@ -35,9 +35,9 @@ export interface BigQueryClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
|
-
* @param params - Optional query parameters
|
|
40
|
+
* @param params - Optional query parameters, bound positionally from the provided array
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
42
42
|
*
|
|
43
43
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -38,7 +38,7 @@ export default api({
|
|
|
38
38
|
}),
|
|
39
39
|
async run(ctx, { date }) {
|
|
40
40
|
const data = await ctx.integrations.databricks.query(
|
|
41
|
-
"SELECT id, value, timestamp FROM data WHERE date =
|
|
41
|
+
"SELECT id, value, timestamp FROM data WHERE date = :PARAM_1",
|
|
42
42
|
DataSchema,
|
|
43
43
|
[date],
|
|
44
44
|
);
|
|
@@ -48,25 +48,29 @@ export default api({
|
|
|
48
48
|
});
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
The SDK accepts Databricks parameters as a positional `params` array, but the
|
|
52
|
+
SQL text should use `:PARAM_1`, `:PARAM_2`, and so on. The first array value
|
|
53
|
+
binds to `:PARAM_1`, the second binds to `:PARAM_2`, and so forth.
|
|
54
|
+
|
|
51
55
|
### Executing INSERT, UPDATE, DELETE Statements
|
|
52
56
|
|
|
53
57
|
```typescript
|
|
54
58
|
// INSERT
|
|
55
59
|
await ctx.integrations.databricks.execute(
|
|
56
|
-
"INSERT INTO metrics (name, value) VALUES (
|
|
60
|
+
"INSERT INTO metrics (name, value) VALUES (:PARAM_1, :PARAM_2)",
|
|
57
61
|
["cpu_usage", "75.5"],
|
|
58
62
|
);
|
|
59
63
|
|
|
60
64
|
// UPDATE
|
|
61
65
|
const updateResult = await ctx.integrations.databricks.execute(
|
|
62
|
-
"UPDATE metrics SET value =
|
|
66
|
+
"UPDATE metrics SET value = :PARAM_1 WHERE name = :PARAM_2",
|
|
63
67
|
["80.0", "cpu_usage"],
|
|
64
68
|
);
|
|
65
69
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
66
70
|
|
|
67
71
|
// DELETE
|
|
68
72
|
const deleteResult = await ctx.integrations.databricks.execute(
|
|
69
|
-
"DELETE FROM metrics WHERE timestamp <
|
|
73
|
+
"DELETE FROM metrics WHERE timestamp < :PARAM_1",
|
|
70
74
|
["2024-01-01"],
|
|
71
75
|
);
|
|
72
76
|
console.log(`Deleted ${deleteResult.rowCount} rows`);
|
|
@@ -100,6 +104,27 @@ All methods accept an optional `metadata` parameter as the last argument for dia
|
|
|
100
104
|
|
|
101
105
|
## Common Pitfalls
|
|
102
106
|
|
|
107
|
+
### Parameter Placeholders Must Match the SDK Contract
|
|
108
|
+
|
|
109
|
+
Pass parameter values as an array, but write the SQL with `:PARAM_n`
|
|
110
|
+
placeholders:
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// WRONG - Positional question marks are not the placeholder syntax this SDK emits
|
|
114
|
+
await ctx.integrations.databricks.query(
|
|
115
|
+
"SELECT * FROM data WHERE date = ?",
|
|
116
|
+
DataSchema,
|
|
117
|
+
["2024-01-01"],
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// CORRECT - Use Databricks placeholders with positional params
|
|
121
|
+
await ctx.integrations.databricks.query(
|
|
122
|
+
"SELECT * FROM data WHERE date = :PARAM_1",
|
|
123
|
+
DataSchema,
|
|
124
|
+
["2024-01-01"],
|
|
125
|
+
);
|
|
126
|
+
```
|
|
127
|
+
|
|
103
128
|
### BIGINT/LONG Values Returned as Strings
|
|
104
129
|
|
|
105
130
|
```typescript
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const data = await databricks.query(
|
|
28
|
-
* 'SELECT * FROM data WHERE date =
|
|
28
|
+
* 'SELECT * FROM data WHERE date = :PARAM_1',
|
|
29
29
|
* DataSchema,
|
|
30
30
|
* ['2024-01-01']
|
|
31
31
|
* );
|
|
@@ -35,9 +35,9 @@ export interface DatabricksClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use :PARAM_1, :PARAM_2, etc. for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
|
-
* @param params - Optional query parameters
|
|
40
|
+
* @param params - Optional query parameters, bound positionally so the first value maps to :PARAM_1
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
42
42
|
*
|
|
43
43
|
* @throws {QueryValidationError} If results don't match schema
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
|
|
7
|
+
import { SUPPORTED_PLUGINS } from "./registry.js";
|
|
8
|
+
|
|
9
|
+
const TEST_DIR = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
type PlaceholderDocsCase = {
|
|
12
|
+
integrationId: string;
|
|
13
|
+
expectedPlaceholder: string;
|
|
14
|
+
rejectsPostgresStyle?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DOC_DIRECTORY_ALIASES = {
|
|
18
|
+
confluent: "kafka",
|
|
19
|
+
graphqlintegration: "graphql",
|
|
20
|
+
redpanda: "kafka",
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
const DOC_DIRECTORY_EXCLUSIONS = new Set(["base"]);
|
|
24
|
+
|
|
25
|
+
function hasDocDirectoryAlias(
|
|
26
|
+
pluginId: string,
|
|
27
|
+
): pluginId is keyof typeof DOC_DIRECTORY_ALIASES {
|
|
28
|
+
return pluginId in DOC_DIRECTORY_ALIASES;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const EXPECTED_DOC_DIRECTORIES = Array.from(
|
|
32
|
+
new Set(
|
|
33
|
+
Object.values(SUPPORTED_PLUGINS)
|
|
34
|
+
.map((pluginId) =>
|
|
35
|
+
hasDocDirectoryAlias(pluginId)
|
|
36
|
+
? DOC_DIRECTORY_ALIASES[pluginId]
|
|
37
|
+
: pluginId,
|
|
38
|
+
)
|
|
39
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory)),
|
|
40
|
+
),
|
|
41
|
+
).sort();
|
|
42
|
+
|
|
43
|
+
const ACTUAL_DOC_DIRECTORIES = readdirSync(TEST_DIR, { withFileTypes: true })
|
|
44
|
+
.filter((entry) => entry.isDirectory())
|
|
45
|
+
.map((entry) => entry.name)
|
|
46
|
+
.filter((directory) => !DOC_DIRECTORY_EXCLUSIONS.has(directory))
|
|
47
|
+
.sort();
|
|
48
|
+
|
|
49
|
+
const PLACEHOLDER_DOC_CASES: PlaceholderDocsCase[] = [
|
|
50
|
+
{ integrationId: "athena", expectedPlaceholder: "?" },
|
|
51
|
+
{ integrationId: "bigquery", expectedPlaceholder: "?" },
|
|
52
|
+
{
|
|
53
|
+
integrationId: "cockroachdb",
|
|
54
|
+
expectedPlaceholder: "$1",
|
|
55
|
+
rejectsPostgresStyle: false,
|
|
56
|
+
},
|
|
57
|
+
{ integrationId: "databricks", expectedPlaceholder: ":PARAM_1" },
|
|
58
|
+
{ integrationId: "dynamodb", expectedPlaceholder: "?" },
|
|
59
|
+
{
|
|
60
|
+
integrationId: "lakebase",
|
|
61
|
+
expectedPlaceholder: "$1",
|
|
62
|
+
rejectsPostgresStyle: false,
|
|
63
|
+
},
|
|
64
|
+
{ integrationId: "mariadb", expectedPlaceholder: "?" },
|
|
65
|
+
{ integrationId: "mssql", expectedPlaceholder: "@PARAM_1" },
|
|
66
|
+
{ integrationId: "mysql", expectedPlaceholder: "?" },
|
|
67
|
+
{ integrationId: "oracledb", expectedPlaceholder: ":1" },
|
|
68
|
+
{
|
|
69
|
+
integrationId: "redshift",
|
|
70
|
+
expectedPlaceholder: "$1",
|
|
71
|
+
rejectsPostgresStyle: false,
|
|
72
|
+
},
|
|
73
|
+
{ integrationId: "snowflake", expectedPlaceholder: "?" },
|
|
74
|
+
{
|
|
75
|
+
integrationId: "snowflakepostgres",
|
|
76
|
+
expectedPlaceholder: "$1",
|
|
77
|
+
rejectsPostgresStyle: false,
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
function readIntegrationFile(integrationId: string, fileName: string): string {
|
|
82
|
+
return readFileSync(resolve(TEST_DIR, integrationId, fileName), "utf8");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
describe("SQL integration documentation", () => {
|
|
86
|
+
it("documents every supported integration directory", () => {
|
|
87
|
+
expect(ACTUAL_DOC_DIRECTORIES).toEqual(EXPECTED_DOC_DIRECTORIES);
|
|
88
|
+
|
|
89
|
+
for (const integrationId of EXPECTED_DOC_DIRECTORIES) {
|
|
90
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "README.md"))).toBe(
|
|
91
|
+
true,
|
|
92
|
+
);
|
|
93
|
+
expect(existsSync(resolve(TEST_DIR, integrationId, "types.ts"))).toBe(
|
|
94
|
+
true,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it.each(PLACEHOLDER_DOC_CASES)(
|
|
100
|
+
"$integrationId README uses $expectedPlaceholder placeholders",
|
|
101
|
+
({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
102
|
+
const readme = readIntegrationFile(integrationId, "README.md");
|
|
103
|
+
|
|
104
|
+
expect(readme).toContain(expectedPlaceholder);
|
|
105
|
+
if (rejectsPostgresStyle) {
|
|
106
|
+
expect(readme).not.toMatch(/\$\d+/);
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
it.each(PLACEHOLDER_DOC_CASES)(
|
|
112
|
+
"$integrationId JSDoc uses $expectedPlaceholder placeholders",
|
|
113
|
+
({ integrationId, expectedPlaceholder, rejectsPostgresStyle = true }) => {
|
|
114
|
+
const typeDocs = readIntegrationFile(integrationId, "types.ts");
|
|
115
|
+
|
|
116
|
+
expect(typeDocs).toContain(expectedPlaceholder);
|
|
117
|
+
if (rejectsPostgresStyle) {
|
|
118
|
+
expect(typeDocs).not.toMatch(/\$\d+/);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
});
|
|
@@ -19,14 +19,14 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
19
19
|
*
|
|
20
20
|
* // Parameterized query
|
|
21
21
|
* const users = await lb.query(
|
|
22
|
-
* 'SELECT * FROM users WHERE status =
|
|
22
|
+
* 'SELECT * FROM users WHERE status = $1',
|
|
23
23
|
* UserSchema,
|
|
24
24
|
* ['active'],
|
|
25
25
|
* );
|
|
26
26
|
*
|
|
27
27
|
* // Execute a mutation
|
|
28
28
|
* const result = await lb.execute(
|
|
29
|
-
* 'INSERT INTO users (name, email) VALUES (
|
|
29
|
+
* 'INSERT INTO users (name, email) VALUES ($1, $2)',
|
|
30
30
|
* ['Alice', 'alice@example.com'],
|
|
31
31
|
* );
|
|
32
32
|
* ```
|
|
@@ -35,7 +35,7 @@ export interface LakebaseClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and return validated rows.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string with
|
|
38
|
+
* @param sql - SQL query string with `$1`, `$2` placeholders for parameters
|
|
39
39
|
* @param schema - Zod schema for validating each result row
|
|
40
40
|
* @param params - Optional query parameters for server-side binding
|
|
41
41
|
* @returns Array of validated rows
|
|
@@ -50,7 +50,7 @@ export interface LakebaseClient extends BaseIntegrationClient {
|
|
|
50
50
|
/**
|
|
51
51
|
* Execute a SQL statement (INSERT, UPDATE, DELETE).
|
|
52
52
|
*
|
|
53
|
-
* @param sql - SQL statement with
|
|
53
|
+
* @param sql - SQL statement with `$1`, `$2` placeholders for parameters
|
|
54
54
|
* @param params - Optional query parameters for server-side binding
|
|
55
55
|
* @returns The affected row count
|
|
56
56
|
*/
|
|
@@ -39,7 +39,7 @@ export default api({
|
|
|
39
39
|
}),
|
|
40
40
|
async run(ctx, { status }) {
|
|
41
41
|
const users = await ctx.integrations.mariadb.query(
|
|
42
|
-
"SELECT id, name, email, created_at FROM users WHERE status =
|
|
42
|
+
"SELECT id, name, email, created_at FROM users WHERE status = ?",
|
|
43
43
|
UserSchema,
|
|
44
44
|
[status],
|
|
45
45
|
);
|
|
@@ -54,13 +54,13 @@ export default api({
|
|
|
54
54
|
```typescript
|
|
55
55
|
// INSERT
|
|
56
56
|
await ctx.integrations.mariadb.execute(
|
|
57
|
-
"INSERT INTO users (name, email) VALUES (
|
|
57
|
+
"INSERT INTO users (name, email) VALUES (?, ?)",
|
|
58
58
|
["John Doe", "john@example.com"],
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
// UPDATE
|
|
62
62
|
const updateResult = await ctx.integrations.mariadb.execute(
|
|
63
|
-
"UPDATE users SET last_login = NOW() WHERE id =
|
|
63
|
+
"UPDATE users SET last_login = NOW() WHERE id = ?",
|
|
64
64
|
[userId],
|
|
65
65
|
);
|
|
66
66
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const users = await mariadb.query(
|
|
28
|
-
* 'SELECT * FROM users WHERE status =
|
|
28
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
29
29
|
* UserSchema,
|
|
30
30
|
* ['active']
|
|
31
31
|
* );
|
|
@@ -35,7 +35,7 @@ export interface MariaDBClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
40
|
* @param params - Optional query parameters
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
@@ -39,7 +39,7 @@ export default api({
|
|
|
39
39
|
}),
|
|
40
40
|
async run(ctx, { status }) {
|
|
41
41
|
const users = await ctx.integrations.mssql.query(
|
|
42
|
-
"SELECT id, name, email, created_at FROM users WHERE status =
|
|
42
|
+
"SELECT id, name, email, created_at FROM users WHERE status = @PARAM_1",
|
|
43
43
|
UserSchema,
|
|
44
44
|
[status],
|
|
45
45
|
);
|
|
@@ -54,13 +54,13 @@ export default api({
|
|
|
54
54
|
```typescript
|
|
55
55
|
// INSERT
|
|
56
56
|
await ctx.integrations.mssql.execute(
|
|
57
|
-
"INSERT INTO users (name, email) VALUES (
|
|
57
|
+
"INSERT INTO users (name, email) VALUES (@PARAM_1, @PARAM_2)",
|
|
58
58
|
["John Doe", "john@example.com"],
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
// UPDATE
|
|
62
62
|
const updateResult = await ctx.integrations.mssql.execute(
|
|
63
|
-
"UPDATE users SET last_login = GETDATE() WHERE id =
|
|
63
|
+
"UPDATE users SET last_login = GETDATE() WHERE id = @PARAM_1",
|
|
64
64
|
[userId],
|
|
65
65
|
);
|
|
66
66
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const users = await mssql.query(
|
|
28
|
-
* 'SELECT * FROM users WHERE status =
|
|
28
|
+
* 'SELECT * FROM users WHERE status = @PARAM_1',
|
|
29
29
|
* UserSchema,
|
|
30
30
|
* ['active']
|
|
31
31
|
* );
|
|
@@ -35,7 +35,7 @@ export interface MSSQLClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use @PARAM_1, @PARAM_2, etc. for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
40
|
* @param params - Optional query parameters
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
@@ -39,7 +39,7 @@ export default api({
|
|
|
39
39
|
}),
|
|
40
40
|
async run(ctx, { status }) {
|
|
41
41
|
const users = await ctx.integrations.mysql.query(
|
|
42
|
-
"SELECT id, name, email, created_at FROM users WHERE status =
|
|
42
|
+
"SELECT id, name, email, created_at FROM users WHERE status = ?",
|
|
43
43
|
UserSchema,
|
|
44
44
|
[status],
|
|
45
45
|
);
|
|
@@ -54,13 +54,13 @@ export default api({
|
|
|
54
54
|
```typescript
|
|
55
55
|
// INSERT
|
|
56
56
|
await ctx.integrations.mysql.execute(
|
|
57
|
-
"INSERT INTO users (name, email) VALUES (
|
|
57
|
+
"INSERT INTO users (name, email) VALUES (?, ?)",
|
|
58
58
|
["John Doe", "john@example.com"],
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
// UPDATE
|
|
62
62
|
const updateResult = await ctx.integrations.mysql.execute(
|
|
63
|
-
"UPDATE users SET last_login = NOW() WHERE id =
|
|
63
|
+
"UPDATE users SET last_login = NOW() WHERE id = ?",
|
|
64
64
|
[userId],
|
|
65
65
|
);
|
|
66
66
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
@@ -90,7 +90,7 @@ const orders = await ctx.integrations.mysql.query(
|
|
|
90
90
|
c.email as customer_email
|
|
91
91
|
FROM orders o
|
|
92
92
|
JOIN customers c ON o.customer_id = c.id
|
|
93
|
-
WHERE o.status =
|
|
93
|
+
WHERE o.status = ?`,
|
|
94
94
|
OrderWithCustomerSchema,
|
|
95
95
|
["pending"],
|
|
96
96
|
);
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const users = await mysql.query(
|
|
28
|
-
* 'SELECT * FROM users WHERE status =
|
|
28
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
29
29
|
* UserSchema,
|
|
30
30
|
* ['active']
|
|
31
31
|
* );
|
|
@@ -35,7 +35,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use ? placeholders for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
40
|
* @param params - Optional query parameters
|
|
41
41
|
* @returns Promise resolving to validated query results
|
|
@@ -52,7 +52,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
52
52
|
* });
|
|
53
53
|
*
|
|
54
54
|
* const users = await mysql.query(
|
|
55
|
-
* 'SELECT * FROM users WHERE status =
|
|
55
|
+
* 'SELECT * FROM users WHERE status = ?',
|
|
56
56
|
* UserSchema,
|
|
57
57
|
* ['active']
|
|
58
58
|
* );
|
|
@@ -75,7 +75,7 @@ export interface MySQLClient extends BaseIntegrationClient {
|
|
|
75
75
|
* @example
|
|
76
76
|
* ```typescript
|
|
77
77
|
* const result = await mysql.execute(
|
|
78
|
-
* 'UPDATE users SET last_login = NOW() WHERE id =
|
|
78
|
+
* 'UPDATE users SET last_login = NOW() WHERE id = ?',
|
|
79
79
|
* [userId]
|
|
80
80
|
* );
|
|
81
81
|
* console.log(`Updated ${result.rowCount} rows`);
|
|
@@ -39,7 +39,7 @@ export default api({
|
|
|
39
39
|
}),
|
|
40
40
|
async run(ctx, { status }) {
|
|
41
41
|
const users = await ctx.integrations.oracledb.query(
|
|
42
|
-
"SELECT ID, NAME, EMAIL, CREATED_AT FROM USERS WHERE STATUS =
|
|
42
|
+
"SELECT ID, NAME, EMAIL, CREATED_AT FROM USERS WHERE STATUS = :1",
|
|
43
43
|
UserSchema,
|
|
44
44
|
[status],
|
|
45
45
|
);
|
|
@@ -54,13 +54,13 @@ export default api({
|
|
|
54
54
|
```typescript
|
|
55
55
|
// INSERT
|
|
56
56
|
await ctx.integrations.oracledb.execute(
|
|
57
|
-
"INSERT INTO USERS (NAME, EMAIL) VALUES (
|
|
57
|
+
"INSERT INTO USERS (NAME, EMAIL) VALUES (:1, :2)",
|
|
58
58
|
["John Doe", "john@example.com"],
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
// UPDATE
|
|
62
62
|
const updateResult = await ctx.integrations.oracledb.execute(
|
|
63
|
-
"UPDATE USERS SET LAST_LOGIN = SYSDATE WHERE ID =
|
|
63
|
+
"UPDATE USERS SET LAST_LOGIN = SYSDATE WHERE ID = :1",
|
|
64
64
|
[userId],
|
|
65
65
|
);
|
|
66
66
|
console.log(`Updated ${updateResult.rowCount} rows`);
|
|
@@ -25,7 +25,7 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
25
25
|
* });
|
|
26
26
|
*
|
|
27
27
|
* const users = await oracledb.query(
|
|
28
|
-
* 'SELECT * FROM users WHERE status =
|
|
28
|
+
* 'SELECT * FROM users WHERE status = :1',
|
|
29
29
|
* UserSchema,
|
|
30
30
|
* ['active']
|
|
31
31
|
* );
|
|
@@ -35,7 +35,7 @@ export interface OracleDBClient extends BaseIntegrationClient {
|
|
|
35
35
|
/**
|
|
36
36
|
* Execute a SQL query and validate results against a Zod schema.
|
|
37
37
|
*
|
|
38
|
-
* @param sql - SQL query string (use
|
|
38
|
+
* @param sql - SQL query string (use :1, :2, etc. for parameters)
|
|
39
39
|
* @param schema - Zod schema to validate the query results
|
|
40
40
|
* @param params - Optional query parameters
|
|
41
41
|
* @returns Promise resolving to validated query results
|