Initial fix for defaulting parameters, switch to null rather than strings, this is important for prepared statements/SQL queries.
This commit is contained in:
parent
ed94459fd8
commit
c32163a9be
|
@ -6,7 +6,7 @@ import { invalidateDynamicVariables } from "../../../threads/utils"
|
|||
import env from "../../../environment"
|
||||
import { events, context, utils, constants } from "@budibase/backend-core"
|
||||
import sdk from "../../../sdk"
|
||||
import { QueryEvent } from "../../../threads/definitions"
|
||||
import { QueryEvent, QueryEventParameters } from "../../../threads/definitions"
|
||||
import {
|
||||
ConfigType,
|
||||
Query,
|
||||
|
@ -18,7 +18,6 @@ import {
|
|||
FieldType,
|
||||
ExecuteQueryRequest,
|
||||
ExecuteQueryResponse,
|
||||
QueryParameter,
|
||||
PreviewQueryRequest,
|
||||
PreviewQueryResponse,
|
||||
} from "@budibase/types"
|
||||
|
@ -29,7 +28,7 @@ const Runner = new Thread(ThreadType.QUERY, {
|
|||
timeoutMs: env.QUERY_THREAD_TIMEOUT,
|
||||
})
|
||||
|
||||
function validateQueryInputs(parameters: Record<string, string>) {
|
||||
function validateQueryInputs(parameters: QueryEventParameters) {
|
||||
for (let entry of Object.entries(parameters)) {
|
||||
const [key, value] = entry
|
||||
if (typeof value !== "string") {
|
||||
|
@ -100,8 +99,10 @@ export async function save(ctx: UserCtx<Query, Query>) {
|
|||
const datasource = await sdk.datasources.get(query.datasourceId)
|
||||
|
||||
let eventFn
|
||||
if (!query._id) {
|
||||
if (!query._id && !query._rev) {
|
||||
query._id = generateQueryID(query.datasourceId)
|
||||
// flag to state whether the default bindings are empty strings (old behaviour) or null
|
||||
query.nullDefaultSupport = true
|
||||
eventFn = () => events.query.created(datasource, query)
|
||||
} else {
|
||||
eventFn = () => events.query.updated(datasource, query)
|
||||
|
@ -135,16 +136,22 @@ function getAuthConfig(ctx: UserCtx) {
|
|||
}
|
||||
|
||||
function enrichParameters(
|
||||
queryParameters: QueryParameter[],
|
||||
requestParameters: Record<string, string> = {}
|
||||
): Record<string, string> {
|
||||
query: Query,
|
||||
requestParameters: QueryEventParameters = {}
|
||||
): QueryEventParameters {
|
||||
const paramNotSet = (val: unknown) => val === "" || val == undefined
|
||||
// first check parameters are all valid
|
||||
validateQueryInputs(requestParameters)
|
||||
// make sure parameters are fully enriched with defaults
|
||||
for (let parameter of queryParameters) {
|
||||
if (!requestParameters[parameter.name]) {
|
||||
requestParameters[parameter.name] = parameter.default
|
||||
for (let parameter of query.parameters) {
|
||||
let value: string | null = requestParameters[parameter.name]
|
||||
if (!value) {
|
||||
value = parameter.default
|
||||
}
|
||||
if (query.nullDefaultSupport && paramNotSet(value)) {
|
||||
value = null
|
||||
}
|
||||
requestParameters[parameter.name] = value
|
||||
}
|
||||
return requestParameters
|
||||
}
|
||||
|
@ -157,10 +164,15 @@ export async function preview(
|
|||
)
|
||||
// preview may not have a queryId as it hasn't been saved, but if it does
|
||||
// this stops dynamic variables from calling the same query
|
||||
const { fields, parameters, queryVerb, transformer, queryId, schema } =
|
||||
ctx.request.body
|
||||
const queryId = ctx.request.body.queryId
|
||||
// the body contains the makings of a query, which has not been saved yet
|
||||
const query: Query = ctx.request.body
|
||||
// hasn't been saved, new query
|
||||
if (!queryId && !query._id) {
|
||||
query.nullDefaultSupport = true
|
||||
}
|
||||
|
||||
let existingSchema = schema
|
||||
let existingSchema = query.schema
|
||||
if (queryId && !existingSchema) {
|
||||
try {
|
||||
const db = context.getAppDB()
|
||||
|
@ -268,13 +280,13 @@ export async function preview(
|
|||
try {
|
||||
const inputs: QueryEvent = {
|
||||
appId: ctx.appId,
|
||||
datasource,
|
||||
queryVerb,
|
||||
fields,
|
||||
parameters: enrichParameters(parameters),
|
||||
transformer,
|
||||
queryVerb: query.queryVerb,
|
||||
fields: query.fields,
|
||||
parameters: enrichParameters(query),
|
||||
transformer: query.transformer,
|
||||
schema: query.schema,
|
||||
queryId,
|
||||
schema,
|
||||
datasource,
|
||||
// have to pass down to the thread runner - can't put into context now
|
||||
environmentVariables: envVars,
|
||||
ctx: {
|
||||
|
@ -336,10 +348,7 @@ async function execute(
|
|||
queryVerb: query.queryVerb,
|
||||
fields: query.fields,
|
||||
pagination: ctx.request.body.pagination,
|
||||
parameters: enrichParameters(
|
||||
query.parameters,
|
||||
ctx.request.body.parameters
|
||||
),
|
||||
parameters: enrichParameters(query, ctx.request.body.parameters),
|
||||
transformer: query.transformer,
|
||||
queryId: ctx.params.queryId,
|
||||
// have to pass down to the thread runner - can't put into context now
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
import { Datasource, QuerySchema, Row } from "@budibase/types"
|
||||
import { Datasource, Row, Query } from "@budibase/types"
|
||||
|
||||
export type WorkerCallback = (error: any, response?: any) => void
|
||||
|
||||
export interface QueryEvent {
|
||||
export interface QueryEvent
|
||||
extends Omit<Query, "datasourceId" | "name" | "parameters" | "readable"> {
|
||||
appId?: string
|
||||
datasource: Datasource
|
||||
queryVerb: string
|
||||
fields: { [key: string]: any }
|
||||
parameters: { [key: string]: unknown }
|
||||
pagination?: any
|
||||
transformer: any
|
||||
queryId?: string
|
||||
environmentVariables?: Record<string, string>
|
||||
parameters: QueryEventParameters
|
||||
ctx?: any
|
||||
schema?: Record<string, QuerySchema | string>
|
||||
}
|
||||
|
||||
export type QueryEventParameters = Record<string, string | null>
|
||||
|
||||
export interface QueryResponse {
|
||||
rows: Row[]
|
||||
keys: string[]
|
||||
|
|
|
@ -15,6 +15,8 @@ export interface Query extends Document {
|
|||
schema: Record<string, QuerySchema | string>
|
||||
readable: boolean
|
||||
queryVerb: string
|
||||
// flag to state whether the default bindings are empty strings (old behaviour) or null
|
||||
nullDefaultSupport?: boolean
|
||||
}
|
||||
|
||||
export interface QueryPreview extends Omit<Query, "_id"> {
|
||||
|
|
Loading…
Reference in New Issue