@powersync/service-sync-rules 0.0.0-dev-20240708103353
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/LICENSE +67 -0
- package/README.md +129 -0
- package/dist/DartSchemaGenerator.d.ts +12 -0
- package/dist/DartSchemaGenerator.js +39 -0
- package/dist/DartSchemaGenerator.js.map +1 -0
- package/dist/ExpressionType.d.ts +33 -0
- package/dist/ExpressionType.js +61 -0
- package/dist/ExpressionType.js.map +1 -0
- package/dist/IdSequence.d.ts +4 -0
- package/dist/IdSequence.js +9 -0
- package/dist/IdSequence.js.map +1 -0
- package/dist/JsSchemaGenerator.d.ts +12 -0
- package/dist/JsSchemaGenerator.js +42 -0
- package/dist/JsSchemaGenerator.js.map +1 -0
- package/dist/SchemaGenerator.d.ts +14 -0
- package/dist/SchemaGenerator.js +26 -0
- package/dist/SchemaGenerator.js.map +1 -0
- package/dist/SourceTableInterface.d.ts +5 -0
- package/dist/SourceTableInterface.js +2 -0
- package/dist/SourceTableInterface.js.map +1 -0
- package/dist/SqlBucketDescriptor.d.ts +37 -0
- package/dist/SqlBucketDescriptor.js +111 -0
- package/dist/SqlBucketDescriptor.js.map +1 -0
- package/dist/SqlDataQuery.d.ts +39 -0
- package/dist/SqlDataQuery.js +239 -0
- package/dist/SqlDataQuery.js.map +1 -0
- package/dist/SqlParameterQuery.d.ts +85 -0
- package/dist/SqlParameterQuery.js +311 -0
- package/dist/SqlParameterQuery.js.map +1 -0
- package/dist/SqlSyncRules.d.ts +52 -0
- package/dist/SqlSyncRules.js +264 -0
- package/dist/SqlSyncRules.js.map +1 -0
- package/dist/StaticSchema.d.ts +26 -0
- package/dist/StaticSchema.js +61 -0
- package/dist/StaticSchema.js.map +1 -0
- package/dist/StaticSqlParameterQuery.d.ts +27 -0
- package/dist/StaticSqlParameterQuery.js +96 -0
- package/dist/StaticSqlParameterQuery.js.map +1 -0
- package/dist/TablePattern.d.ts +17 -0
- package/dist/TablePattern.js +56 -0
- package/dist/TablePattern.js.map +1 -0
- package/dist/TableQuerySchema.d.ts +9 -0
- package/dist/TableQuerySchema.js +34 -0
- package/dist/TableQuerySchema.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +58 -0
- package/dist/errors.js.map +1 -0
- package/dist/generators.d.ts +6 -0
- package/dist/generators.js +7 -0
- package/dist/generators.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/json_schema.d.ts +3 -0
- package/dist/json_schema.js +52 -0
- package/dist/json_schema.js.map +1 -0
- package/dist/request_functions.d.ts +17 -0
- package/dist/request_functions.js +41 -0
- package/dist/request_functions.js.map +1 -0
- package/dist/sql_filters.d.ts +125 -0
- package/dist/sql_filters.js +599 -0
- package/dist/sql_filters.js.map +1 -0
- package/dist/sql_functions.d.ts +61 -0
- package/dist/sql_functions.js +863 -0
- package/dist/sql_functions.js.map +1 -0
- package/dist/sql_support.d.ts +25 -0
- package/dist/sql_support.js +254 -0
- package/dist/sql_support.js.map +1 -0
- package/dist/types.d.ts +262 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.js +167 -0
- package/dist/utils.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SelectedColumn } from 'pgsql-ast-parser';
|
|
2
|
+
import { SqlRuleError } from './errors.js';
|
|
3
|
+
import { ColumnDefinition } from './ExpressionType.js';
|
|
4
|
+
import { SourceTableInterface } from './SourceTableInterface.js';
|
|
5
|
+
import { SqlTools } from './sql_filters.js';
|
|
6
|
+
import { TablePattern } from './TablePattern.js';
|
|
7
|
+
import { EvaluationResult, ParameterMatchClause, QueryParameters, QuerySchema, SourceSchema, SqliteRow } from './types.js';
|
|
8
|
+
interface RowValueExtractor {
|
|
9
|
+
extract(tables: QueryParameters, into: SqliteRow): void;
|
|
10
|
+
getTypes(schema: QuerySchema, into: Record<string, ColumnDefinition>): void;
|
|
11
|
+
}
|
|
12
|
+
export declare class SqlDataQuery {
|
|
13
|
+
static fromSql(descriptor_name: string, bucket_parameters: string[], sql: string, schema?: SourceSchema): SqlDataQuery;
|
|
14
|
+
sourceTable?: TablePattern;
|
|
15
|
+
table?: string;
|
|
16
|
+
sql?: string;
|
|
17
|
+
columns?: SelectedColumn[];
|
|
18
|
+
extractors: RowValueExtractor[];
|
|
19
|
+
filter?: ParameterMatchClause;
|
|
20
|
+
descriptor_name?: string;
|
|
21
|
+
bucket_parameters?: string[];
|
|
22
|
+
tools?: SqlTools;
|
|
23
|
+
ruleId?: string;
|
|
24
|
+
errors: SqlRuleError[];
|
|
25
|
+
constructor();
|
|
26
|
+
applies(table: SourceTableInterface): boolean | undefined;
|
|
27
|
+
addSpecialParameters(table: SourceTableInterface, row: SqliteRow): SqliteRow;
|
|
28
|
+
getOutputName(sourceTable: string): string;
|
|
29
|
+
isUnaliasedWildcard(): boolean;
|
|
30
|
+
evaluateRow(table: SourceTableInterface, row: SqliteRow): EvaluationResult[];
|
|
31
|
+
private transformRow;
|
|
32
|
+
columnOutputNames(): string[];
|
|
33
|
+
getColumnOutputs(schema: SourceSchema): {
|
|
34
|
+
name: string;
|
|
35
|
+
columns: ColumnDefinition[];
|
|
36
|
+
}[];
|
|
37
|
+
private getColumnOutputsFor;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { JSONBig } from '@powersync/service-jsonbig';
|
|
2
|
+
import { parse } from 'pgsql-ast-parser';
|
|
3
|
+
import { SqlRuleError } from './errors.js';
|
|
4
|
+
import { ExpressionType } from './ExpressionType.js';
|
|
5
|
+
import { SqlTools } from './sql_filters.js';
|
|
6
|
+
import { castAsText } from './sql_functions.js';
|
|
7
|
+
import { checkUnsupportedFeatures, isClauseError } from './sql_support.js';
|
|
8
|
+
import { TablePattern } from './TablePattern.js';
|
|
9
|
+
import { filterJsonRow, getBucketId, isSelectStatement } from './utils.js';
|
|
10
|
+
import { TableQuerySchema } from './TableQuerySchema.js';
|
|
11
|
+
export class SqlDataQuery {
|
|
12
|
+
static fromSql(descriptor_name, bucket_parameters, sql, schema) {
|
|
13
|
+
const parsed = parse(sql, { locationTracking: true });
|
|
14
|
+
const rows = new SqlDataQuery();
|
|
15
|
+
if (parsed.length > 1) {
|
|
16
|
+
throw new SqlRuleError('Only a single SELECT statement is supported', sql, parsed[1]?._location);
|
|
17
|
+
}
|
|
18
|
+
const q = parsed[0];
|
|
19
|
+
if (!isSelectStatement(q)) {
|
|
20
|
+
throw new SqlRuleError('Only SELECT statements are supported', sql, q._location);
|
|
21
|
+
}
|
|
22
|
+
rows.errors.push(...checkUnsupportedFeatures(sql, q));
|
|
23
|
+
if (q.from == null || q.from.length != 1 || q.from[0].type != 'table') {
|
|
24
|
+
throw new SqlRuleError('Must SELECT from a single table', sql, q.from?.[0]._location);
|
|
25
|
+
}
|
|
26
|
+
const tableRef = q.from?.[0].name;
|
|
27
|
+
if (tableRef?.name == null) {
|
|
28
|
+
throw new SqlRuleError('Must SELECT from a single table', sql, q.from?.[0]._location);
|
|
29
|
+
}
|
|
30
|
+
const alias = tableRef.alias ?? tableRef.name;
|
|
31
|
+
const sourceTable = new TablePattern(tableRef.schema, tableRef.name);
|
|
32
|
+
let querySchema = undefined;
|
|
33
|
+
if (schema) {
|
|
34
|
+
const tables = schema.getTables(sourceTable);
|
|
35
|
+
if (tables.length == 0) {
|
|
36
|
+
const e = new SqlRuleError(`Table ${sourceTable.schema}.${sourceTable.tablePattern} not found`, sql, q.from?.[0]?._location);
|
|
37
|
+
e.type = 'warning';
|
|
38
|
+
rows.errors.push(e);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
querySchema = new TableQuerySchema(tables, alias);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const where = q.where;
|
|
45
|
+
const tools = new SqlTools({
|
|
46
|
+
table: alias,
|
|
47
|
+
parameter_tables: ['bucket'],
|
|
48
|
+
value_tables: [alias],
|
|
49
|
+
sql,
|
|
50
|
+
schema: querySchema
|
|
51
|
+
});
|
|
52
|
+
const filter = tools.compileWhereClause(where);
|
|
53
|
+
const inputParameterNames = filter.inputParameters.map((p) => p.key);
|
|
54
|
+
const bucketParameterNames = bucket_parameters.map((p) => `bucket.${p}`);
|
|
55
|
+
const allParams = new Set([...inputParameterNames, ...bucketParameterNames]);
|
|
56
|
+
if ((!filter.error && allParams.size != filter.inputParameters.length) ||
|
|
57
|
+
allParams.size != bucket_parameters.length) {
|
|
58
|
+
rows.errors.push(new SqlRuleError(`Query must cover all bucket parameters. Expected: ${JSONBig.stringify(bucketParameterNames)} Got: ${JSONBig.stringify(inputParameterNames)}`, sql, q._location));
|
|
59
|
+
}
|
|
60
|
+
rows.sourceTable = sourceTable;
|
|
61
|
+
rows.table = alias;
|
|
62
|
+
rows.sql = sql;
|
|
63
|
+
rows.filter = filter;
|
|
64
|
+
rows.descriptor_name = descriptor_name;
|
|
65
|
+
rows.bucket_parameters = bucket_parameters;
|
|
66
|
+
rows.columns = q.columns ?? [];
|
|
67
|
+
rows.tools = tools;
|
|
68
|
+
let hasId = false;
|
|
69
|
+
for (let column of q.columns ?? []) {
|
|
70
|
+
const name = tools.getOutputName(column);
|
|
71
|
+
if (name != '*') {
|
|
72
|
+
const clause = tools.compileRowValueExtractor(column.expr);
|
|
73
|
+
if (isClauseError(clause)) {
|
|
74
|
+
// Error logged already
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
rows.extractors.push({
|
|
78
|
+
extract: (tables, output) => {
|
|
79
|
+
output[name] = clause.evaluate(tables);
|
|
80
|
+
},
|
|
81
|
+
getTypes(schema, into) {
|
|
82
|
+
into[name] = { name, type: clause.getType(schema) };
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
rows.extractors.push({
|
|
88
|
+
extract: (tables, output) => {
|
|
89
|
+
const row = tables[alias];
|
|
90
|
+
for (let key in row) {
|
|
91
|
+
if (key.startsWith('_')) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
output[key] ?? (output[key] = row[key]);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
getTypes(schema, into) {
|
|
98
|
+
var _a;
|
|
99
|
+
for (let column of schema.getColumns(alias)) {
|
|
100
|
+
into[_a = column.name] ?? (into[_a] = column);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (name == 'id' || name == '*') {
|
|
106
|
+
hasId = true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (!hasId) {
|
|
110
|
+
rows.errors.push(new SqlRuleError(`Query must return an "id" column`, sql, q.columns?.[0]._location));
|
|
111
|
+
}
|
|
112
|
+
rows.errors.push(...tools.errors);
|
|
113
|
+
return rows;
|
|
114
|
+
}
|
|
115
|
+
constructor() {
|
|
116
|
+
this.extractors = [];
|
|
117
|
+
this.errors = [];
|
|
118
|
+
}
|
|
119
|
+
applies(table) {
|
|
120
|
+
return this.sourceTable?.matches(table);
|
|
121
|
+
}
|
|
122
|
+
addSpecialParameters(table, row) {
|
|
123
|
+
if (this.sourceTable.isWildcard) {
|
|
124
|
+
return {
|
|
125
|
+
...row,
|
|
126
|
+
_table_suffix: this.sourceTable.suffix(table.table)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return row;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
getOutputName(sourceTable) {
|
|
134
|
+
if (this.isUnaliasedWildcard()) {
|
|
135
|
+
// Wildcard without alias - use source
|
|
136
|
+
return sourceTable;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return this.table;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
isUnaliasedWildcard() {
|
|
143
|
+
return this.sourceTable.isWildcard && this.table == this.sourceTable.tablePattern;
|
|
144
|
+
}
|
|
145
|
+
evaluateRow(table, row) {
|
|
146
|
+
try {
|
|
147
|
+
const tables = { [this.table]: this.addSpecialParameters(table, row) };
|
|
148
|
+
const bucketParameters = this.filter.filterRow(tables);
|
|
149
|
+
const bucketIds = bucketParameters.map((params) => getBucketId(this.descriptor_name, this.bucket_parameters, params));
|
|
150
|
+
const data = this.transformRow(tables);
|
|
151
|
+
let id = data.id;
|
|
152
|
+
if (typeof id != 'string') {
|
|
153
|
+
// While an explicit cast would be better, this covers against very common
|
|
154
|
+
// issues when initially testing out sync, for example when the id column is an
|
|
155
|
+
// auto-incrementing integer.
|
|
156
|
+
// If there is no id column, we use a blank id. This will result in the user syncing
|
|
157
|
+
// a single arbitrary row for this table - better than just not being able to sync
|
|
158
|
+
// anything.
|
|
159
|
+
id = castAsText(id) ?? '';
|
|
160
|
+
}
|
|
161
|
+
const outputTable = this.getOutputName(table.table);
|
|
162
|
+
return bucketIds.map((bucketId) => {
|
|
163
|
+
return {
|
|
164
|
+
bucket: bucketId,
|
|
165
|
+
table: outputTable,
|
|
166
|
+
id: id,
|
|
167
|
+
data,
|
|
168
|
+
ruleId: this.ruleId
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
return [{ error: e.message ?? `Evaluating data query failed` }];
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
transformRow(tables) {
|
|
177
|
+
let result = {};
|
|
178
|
+
for (let extractor of this.extractors) {
|
|
179
|
+
extractor.extract(tables, result);
|
|
180
|
+
}
|
|
181
|
+
return filterJsonRow(result);
|
|
182
|
+
}
|
|
183
|
+
columnOutputNames() {
|
|
184
|
+
return this.columns.map((c) => {
|
|
185
|
+
return this.tools.getOutputName(c);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
getColumnOutputs(schema) {
|
|
189
|
+
let result = [];
|
|
190
|
+
if (this.isUnaliasedWildcard()) {
|
|
191
|
+
// Separate results
|
|
192
|
+
for (let schemaTable of schema.getTables(this.sourceTable)) {
|
|
193
|
+
let output = {};
|
|
194
|
+
this.getColumnOutputsFor(schemaTable, output);
|
|
195
|
+
result.push({
|
|
196
|
+
name: this.getOutputName(schemaTable.table),
|
|
197
|
+
columns: Object.values(output)
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Merged results
|
|
203
|
+
let output = {};
|
|
204
|
+
for (let schemaTable of schema.getTables(this.sourceTable)) {
|
|
205
|
+
this.getColumnOutputsFor(schemaTable, output);
|
|
206
|
+
}
|
|
207
|
+
result.push({
|
|
208
|
+
name: this.table,
|
|
209
|
+
columns: Object.values(output)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
getColumnOutputsFor(schemaTable, output) {
|
|
215
|
+
const querySchema = {
|
|
216
|
+
getType: (table, column) => {
|
|
217
|
+
if (table == this.table) {
|
|
218
|
+
return schemaTable.getType(column) ?? ExpressionType.NONE;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// TODO: bucket parameters?
|
|
222
|
+
return ExpressionType.NONE;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
getColumns: (table) => {
|
|
226
|
+
if (table == this.table) {
|
|
227
|
+
return schemaTable.getColumns();
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
for (let extractor of this.extractors) {
|
|
235
|
+
extractor.getTypes(querySchema, output);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=SqlDataQuery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlDataQuery.js","sourceRoot":"","sources":["../src/SqlDataQuery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { SelectedColumn } from 'pgsql-ast-parser';
|
|
2
|
+
import { SqlRuleError } from './errors.js';
|
|
3
|
+
import { SourceTableInterface } from './SourceTableInterface.js';
|
|
4
|
+
import { SqlTools } from './sql_filters.js';
|
|
5
|
+
import { StaticSqlParameterQuery } from './StaticSqlParameterQuery.js';
|
|
6
|
+
import { TablePattern } from './TablePattern.js';
|
|
7
|
+
import { EvaluatedParametersResult, InputParameter, ParameterMatchClause, ParameterValueClause, QueryBucketIdOptions, QueryParseOptions, RequestParameters, RowValueClause, SourceSchema, SqliteJsonRow, SqliteJsonValue, SqliteRow } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Represents a parameter query, such as:
|
|
10
|
+
*
|
|
11
|
+
* SELECT id as user_id FROM users WHERE users.user_id = token_parameters.user_id
|
|
12
|
+
* SELECT id as user_id, token_parameters.is_admin as is_admin FROM users WHERE users.user_id = token_parameters.user_id
|
|
13
|
+
*/
|
|
14
|
+
export declare class SqlParameterQuery {
|
|
15
|
+
static fromSql(descriptor_name: string, sql: string, schema?: SourceSchema, options?: QueryParseOptions): SqlParameterQuery | StaticSqlParameterQuery;
|
|
16
|
+
sourceTable?: TablePattern;
|
|
17
|
+
table?: string;
|
|
18
|
+
sql?: string;
|
|
19
|
+
columns?: SelectedColumn[];
|
|
20
|
+
lookup_columns?: SelectedColumn[];
|
|
21
|
+
static_columns?: SelectedColumn[];
|
|
22
|
+
/**
|
|
23
|
+
* Example: SELECT *user.id* FROM users WHERE ...
|
|
24
|
+
*/
|
|
25
|
+
lookup_extractors: Record<string, RowValueClause>;
|
|
26
|
+
/**
|
|
27
|
+
* Example: SELECT *token_parameters.user_id*
|
|
28
|
+
*/
|
|
29
|
+
parameter_extractors: Record<string, ParameterValueClause>;
|
|
30
|
+
filter?: ParameterMatchClause;
|
|
31
|
+
descriptor_name?: string;
|
|
32
|
+
/** _Input_ token / user parameters */
|
|
33
|
+
input_parameters?: InputParameter[];
|
|
34
|
+
/** If specified, an input parameter that expands to an array. */
|
|
35
|
+
expanded_input_parameter?: InputParameter;
|
|
36
|
+
/**
|
|
37
|
+
* _Output_ bucket parameters.
|
|
38
|
+
*
|
|
39
|
+
* Each one of these will be present in either lookup_extractors or static_extractors.
|
|
40
|
+
*/
|
|
41
|
+
bucket_parameters?: string[];
|
|
42
|
+
id?: string;
|
|
43
|
+
tools?: SqlTools;
|
|
44
|
+
errors: SqlRuleError[];
|
|
45
|
+
constructor();
|
|
46
|
+
applies(table: SourceTableInterface): boolean;
|
|
47
|
+
evaluateParameterRow(row: SqliteRow): EvaluatedParametersResult[];
|
|
48
|
+
transformRows(row: SqliteRow): SqliteRow[];
|
|
49
|
+
/**
|
|
50
|
+
* Given partial parameter rows, turn into bucket ids.
|
|
51
|
+
*/
|
|
52
|
+
resolveBucketIds(bucketParameters: SqliteJsonRow[], parameters: RequestParameters): string[];
|
|
53
|
+
/**
|
|
54
|
+
* Given sync parameters, get lookups we need to perform on the database.
|
|
55
|
+
*
|
|
56
|
+
* Each lookup is [bucket definition name, parameter query index, ...lookup values]
|
|
57
|
+
*/
|
|
58
|
+
getLookups(parameters: RequestParameters): SqliteJsonValue[][];
|
|
59
|
+
/**
|
|
60
|
+
* Given sync parameters (token and user parameters), return bucket ids.
|
|
61
|
+
*
|
|
62
|
+
* This is done in three steps:
|
|
63
|
+
* 1. Given the parameters, get lookups we need to perform on the database.
|
|
64
|
+
* 2. Perform the lookups, returning parameter sets (partial rows).
|
|
65
|
+
* 3. Given the parameter sets, resolve bucket ids.
|
|
66
|
+
*/
|
|
67
|
+
queryBucketIds(options: QueryBucketIdOptions): Promise<string[]>;
|
|
68
|
+
get hasAuthenticatedBucketParameters(): boolean;
|
|
69
|
+
get hasAuthenticatedMatchClause(): boolean;
|
|
70
|
+
get usesUnauthenticatedRequestParameters(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Safe:
|
|
73
|
+
* SELECT id as user_id FROM users WHERE users.user_id = request.user_id()
|
|
74
|
+
* SELECT request.jwt() ->> 'org_id' as org_id, id as project_id FROM projects WHERE id = request.parameters() ->> 'project_id'
|
|
75
|
+
* SELECT id as project_id FROM projects WHERE org_id = request.jwt() ->> 'org_id' AND id = request.parameters() ->> 'project_id'
|
|
76
|
+
* SELECT id as category_id FROM categories
|
|
77
|
+
*
|
|
78
|
+
* Dangerous:
|
|
79
|
+
* SELECT id as project_id FROM projects WHERE id = request.parameters() ->> 'project_id'
|
|
80
|
+
* SELECT id as project_id FROM projects WHERE id = request.parameters() ->> 'project_id' AND request.jwt() ->> 'role' = 'authenticated'
|
|
81
|
+
* SELECT id as category_id, request.parameters() ->> 'project_id' as project_id FROM categories
|
|
82
|
+
* SELECT id as category_id FROM categories WHERE request.parameters() ->> 'include_categories'
|
|
83
|
+
*/
|
|
84
|
+
get usesDangerousRequestParameters(): boolean;
|
|
85
|
+
}
|