1
0
Fork 0
mirror of synced 2024-07-13 02:05:54 +12:00

fix issue where schema wasn't updating types when a query was run (#14004)

* fix issue where schema wasn't updating types when a query was run

* add tests for schema matching
This commit is contained in:
Peter Clement 2024-06-25 08:51:35 +01:00 committed by GitHub
parent 4ac9b657e5
commit f3d466f255
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 182 additions and 5 deletions

View file

@ -233,9 +233,9 @@
response.info = response.info || { code: 200 }
// if existing schema, copy over what it is
if (schema) {
for (let [name, field] of Object.entries(schema)) {
if (response.schema[name]) {
response.schema[name] = field
for (let [name, field] of Object.entries(response.schema)) {
if (!schema[name]) {
schema[name] = field
}
}
}

View file

@ -311,8 +311,8 @@ export async function preview(
// if existing schema, update to include any previous schema keys
if (existingSchema) {
for (let key of Object.keys(previewSchema)) {
if (existingSchema[key]) {
for (let key of Object.keys(existingSchema)) {
if (!previewSchema[key]) {
previewSchema[key] = existingSchema[key]
}
}

View file

@ -250,6 +250,67 @@ describe.each(
expect(events.query.previewed).toHaveBeenCalledTimes(1)
})
it("should update schema when column type changes from number to string", async () => {
const tableName = "schema_change_test"
await client.schema.dropTableIfExists(tableName)
await client.schema.createTable(tableName, table => {
table.increments("id").primary()
table.string("name")
table.integer("data")
})
await client(tableName).insert({
name: "test",
data: 123,
})
const firstPreview = await config.api.query.preview({
datasourceId: datasource._id!,
name: "Test Query",
queryVerb: "read",
fields: {
sql: `SELECT * FROM ${tableName}`,
},
parameters: [],
transformer: "return data",
schema: {},
readable: true,
})
expect(firstPreview.schema).toEqual(
expect.objectContaining({
data: { type: "number", name: "data" },
})
)
await client.schema.alterTable(tableName, table => {
table.string("data").alter()
})
await client(tableName).update({
data: "string value",
})
const secondPreview = await config.api.query.preview({
datasourceId: datasource._id!,
name: "Test Query",
queryVerb: "read",
fields: {
sql: `SELECT * FROM ${tableName}`,
},
parameters: [],
transformer: "return data",
schema: firstPreview.schema,
readable: true,
})
expect(secondPreview.schema).toEqual(
expect.objectContaining({
data: { type: "string", name: "data" },
})
)
})
it("should work with static variables", async () => {
await config.api.datasource.update({
...datasource,

View file

@ -137,6 +137,67 @@ describe("/queries", () => {
})
})
it("should update schema when structure changes from object to array", async () => {
const name = generator.guid()
await withCollection(async collection => {
await collection.insertOne({ name, field: { subfield: "value" } })
})
const firstPreview = await config.api.query.preview({
name: "Test Query",
datasourceId: datasource._id!,
fields: {
json: { name: { $eq: name } },
extra: {
collection,
actionType: "findOne",
},
},
schema: {},
queryVerb: "read",
parameters: [],
transformer: "return data",
readable: true,
})
expect(firstPreview.schema).toEqual(
expect.objectContaining({
field: { type: "json", name: "field" },
})
)
await withCollection(async collection => {
await collection.updateOne(
{ name },
{ $set: { field: ["value1", "value2"] } }
)
})
const secondPreview = await config.api.query.preview({
name: "Test Query",
datasourceId: datasource._id!,
fields: {
json: { name: { $eq: name } },
extra: {
collection,
actionType: "findOne",
},
},
schema: firstPreview.schema,
queryVerb: "read",
parameters: [],
transformer: "return data",
readable: true,
})
expect(secondPreview.schema).toEqual(
expect.objectContaining({
field: { type: "array", name: "field" },
})
)
})
it("should generate a nested schema based on all of the nested items", async () => {
const name = generator.guid()
const item = {

View file

@ -92,6 +92,61 @@ describe("rest", () => {
expect(cached.rows[0].name).toEqual("one")
})
it("should update schema when structure changes from JSON to array", async () => {
const datasource = await config.api.datasource.create({
name: generator.guid(),
type: "test",
source: SourceName.REST,
config: {},
})
nock("http://www.example.com")
.get("/")
.reply(200, [{ obj: {}, id: "1" }])
const firstResponse = await config.api.query.preview({
datasourceId: datasource._id!,
name: "test query",
parameters: [],
queryVerb: "read",
transformer: "",
schema: {},
readable: true,
fields: {
path: "www.example.com",
},
})
expect(firstResponse.schema).toEqual({
obj: { type: "json", name: "obj" },
id: { type: "string", name: "id" },
})
nock.cleanAll()
nock("http://www.example.com")
.get("/")
.reply(200, [{ obj: [], id: "1" }])
const secondResponse = await config.api.query.preview({
datasourceId: datasource._id!,
name: "test query",
parameters: [],
queryVerb: "read",
transformer: "",
schema: firstResponse.schema,
readable: true,
fields: {
path: "www.example.com",
},
})
expect(secondResponse.schema).toEqual({
obj: { type: "array", name: "obj" },
id: { type: "string", name: "id" },
})
})
it("should parse global and query level header mappings", async () => {
const datasource = await config.api.datasource.create({
name: generator.guid(),