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:
parent
4ac9b657e5
commit
f3d466f255
|
@ -233,9 +233,9 @@
|
||||||
response.info = response.info || { code: 200 }
|
response.info = response.info || { code: 200 }
|
||||||
// if existing schema, copy over what it is
|
// if existing schema, copy over what it is
|
||||||
if (schema) {
|
if (schema) {
|
||||||
for (let [name, field] of Object.entries(schema)) {
|
for (let [name, field] of Object.entries(response.schema)) {
|
||||||
if (response.schema[name]) {
|
if (!schema[name]) {
|
||||||
response.schema[name] = field
|
schema[name] = field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,8 +311,8 @@ export async function preview(
|
||||||
|
|
||||||
// if existing schema, update to include any previous schema keys
|
// if existing schema, update to include any previous schema keys
|
||||||
if (existingSchema) {
|
if (existingSchema) {
|
||||||
for (let key of Object.keys(previewSchema)) {
|
for (let key of Object.keys(existingSchema)) {
|
||||||
if (existingSchema[key]) {
|
if (!previewSchema[key]) {
|
||||||
previewSchema[key] = existingSchema[key]
|
previewSchema[key] = existingSchema[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,6 +250,67 @@ describe.each(
|
||||||
expect(events.query.previewed).toHaveBeenCalledTimes(1)
|
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 () => {
|
it("should work with static variables", async () => {
|
||||||
await config.api.datasource.update({
|
await config.api.datasource.update({
|
||||||
...datasource,
|
...datasource,
|
||||||
|
|
|
@ -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 () => {
|
it("should generate a nested schema based on all of the nested items", async () => {
|
||||||
const name = generator.guid()
|
const name = generator.guid()
|
||||||
const item = {
|
const item = {
|
||||||
|
|
|
@ -92,6 +92,61 @@ describe("rest", () => {
|
||||||
expect(cached.rows[0].name).toEqual("one")
|
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 () => {
|
it("should parse global and query level header mappings", async () => {
|
||||||
const datasource = await config.api.datasource.create({
|
const datasource = await config.api.datasource.create({
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
|
|
Loading…
Reference in New Issue