Merge branch 'feature/opinionated-sql' of github.com:Budibase/budibase into feature/opinionated-sql
This commit is contained in:
commit
d93c4b02ae
|
@ -84,7 +84,7 @@ const createScreen = table => {
|
||||||
.customProps({
|
.customProps({
|
||||||
dataSource: {
|
dataSource: {
|
||||||
label: table.name,
|
label: table.name,
|
||||||
name: `all_${table._id}`,
|
name: table._id,
|
||||||
tableId: table._id,
|
tableId: table._id,
|
||||||
type: "table",
|
type: "table",
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,7 +75,7 @@ const createScreen = table => {
|
||||||
.customProps({
|
.customProps({
|
||||||
dataSource: {
|
dataSource: {
|
||||||
label: table.name,
|
label: table.name,
|
||||||
name: `all_${table._id}`,
|
name: table._id,
|
||||||
tableId: table._id,
|
tableId: table._id,
|
||||||
type: "table",
|
type: "table",
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,10 +27,9 @@
|
||||||
|
|
||||||
// Fetch rows for specified table
|
// Fetch rows for specified table
|
||||||
$: {
|
$: {
|
||||||
if ($views.selected?.name?.startsWith("all_")) {
|
|
||||||
loading = true
|
loading = true
|
||||||
const loadingTableId = $tables.selected?._id
|
const loadingTableId = $tables.selected?._id
|
||||||
api.fetchDataForView($views.selected).then(rows => {
|
api.fetchDataForTable($tables.selected._id).then(rows => {
|
||||||
loading = false
|
loading = false
|
||||||
|
|
||||||
// If we started a slow request then quickly change table, sometimes
|
// If we started a slow request then quickly change table, sometimes
|
||||||
|
@ -43,7 +42,6 @@
|
||||||
data = rows || []
|
data = rows || []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
|
|
|
@ -20,11 +20,9 @@
|
||||||
|
|
||||||
// Fetch rows for specified view
|
// Fetch rows for specified view
|
||||||
$: {
|
$: {
|
||||||
if (!name.startsWith("all_")) {
|
|
||||||
loading = true
|
loading = true
|
||||||
fetchViewData(name, view.field, view.groupBy, view.calculation)
|
fetchViewData(name, view.field, view.groupBy, view.calculation)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchViewData(name, field, groupBy, calculation) {
|
async function fetchViewData(name, field, groupBy, calculation) {
|
||||||
const _tables = $tables.list
|
const _tables = $tables.list
|
||||||
|
@ -32,6 +30,7 @@
|
||||||
const thisView = allTableViews.filter(
|
const thisView = allTableViews.filter(
|
||||||
views => views != null && views[name] != null
|
views => views != null && views[name] != null
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
// don't fetch view data if the view no longer exists
|
// don't fetch view data if the view no longer exists
|
||||||
if (!thisView) {
|
if (!thisView) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -21,8 +21,8 @@ export async function deleteRow(row) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDataForView(view) {
|
export async function fetchDataForTable(tableId) {
|
||||||
const FETCH_ROWS_URL = `/api/views/${view.name}`
|
const FETCH_ROWS_URL = `/api/${tableId}/rows`
|
||||||
|
|
||||||
const response = await api.get(FETCH_ROWS_URL)
|
const response = await api.get(FETCH_ROWS_URL)
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
border={idx > 0}
|
border={idx > 0}
|
||||||
icon={table._id === TableNames.USERS ? "UserGroup" : "Table"}
|
icon={table._id === TableNames.USERS ? "UserGroup" : "Table"}
|
||||||
text={table.name}
|
text={table.name}
|
||||||
selected={selectedView === `all_${table._id}`}
|
selected={selectedView === table._id}
|
||||||
on:click={() => selectTable(table)}
|
on:click={() => selectTable(table)}
|
||||||
>
|
>
|
||||||
{#if table._id !== TableNames.USERS}
|
{#if table._id !== TableNames.USERS}
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function createTablesStore() {
|
||||||
selected: table,
|
selected: table,
|
||||||
draft: cloneDeep(table),
|
draft: cloneDeep(table),
|
||||||
}))
|
}))
|
||||||
views.select({ name: `all_${table._id}` })
|
views.select({ name: table._id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ describe("Tables Store", () => {
|
||||||
await store.select(tableToSelect)
|
await store.select(tableToSelect)
|
||||||
|
|
||||||
expect(get(store).selected).toEqual(tableToSelect)
|
expect(get(store).selected).toEqual(tableToSelect)
|
||||||
expect(get(views).selected).toEqual({ name: `all_${tableToSelect._id}` })
|
expect(get(views).selected).toEqual({ name: tableToSelect._id })
|
||||||
})
|
})
|
||||||
|
|
||||||
it("saving a table also selects it", async () => {
|
it("saving a table also selects it", async () => {
|
||||||
|
|
|
@ -127,9 +127,11 @@ exports.bulkDestroy = async ctx => {
|
||||||
// TODO: this can probably be optimised to a single SQL statement in the future
|
// TODO: this can probably be optimised to a single SQL statement in the future
|
||||||
let promises = []
|
let promises = []
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
promises.push(handleRequest(appId, DataSourceOperation.DELETE, tableId, {
|
promises.push(
|
||||||
|
handleRequest(appId, DataSourceOperation.DELETE, tableId, {
|
||||||
id: row._id,
|
id: row._id,
|
||||||
}))
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
await Promise.all(promises)
|
await Promise.all(promises)
|
||||||
return { response: { ok: true }, rows }
|
return { response: { ok: true }, rows }
|
||||||
|
|
|
@ -309,7 +309,7 @@ describe("/rows", () => {
|
||||||
it("should be able to fetch tables contents via 'view'", async () => {
|
it("should be able to fetch tables contents via 'view'", async () => {
|
||||||
const row = await config.createRow()
|
const row = await config.createRow()
|
||||||
const res = await request
|
const res = await request
|
||||||
.get(`/api/views/all_${table._id}`)
|
.get(`/api/views/${table._id}`)
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
|
@ -2,6 +2,7 @@ const Sql = require("../base/sql")
|
||||||
const { Pool } = require("pg")
|
const { Pool } = require("pg")
|
||||||
const { FieldTypes } = require("../../constants")
|
const { FieldTypes } = require("../../constants")
|
||||||
const { FIELD_TYPES } = require("../Integration")
|
const { FIELD_TYPES } = require("../Integration")
|
||||||
|
const { SEPARATOR } = require("@budibase/auth/db")
|
||||||
|
|
||||||
const TYPE_MAP = {
|
const TYPE_MAP = {
|
||||||
text: FieldTypes.LONGFORM,
|
text: FieldTypes.LONGFORM,
|
||||||
|
@ -60,7 +61,7 @@ class PostgresPlus extends Sql {
|
||||||
"select * from information_schema.columns where table_schema = 'public'"
|
"select * from information_schema.columns where table_schema = 'public'"
|
||||||
|
|
||||||
PRIMARY_KEYS_SQL = `
|
PRIMARY_KEYS_SQL = `
|
||||||
select tc.table_schema, tc.table_name, tc.column_name, kc.column_name as primary_key
|
select tc.table_schema, tc.table_name, kc.column_name as primary_key
|
||||||
from information_schema.table_constraints tc
|
from information_schema.table_constraints tc
|
||||||
join
|
join
|
||||||
information_schema.key_column_usage kc on kc.table_name = tc.table_name
|
information_schema.key_column_usage kc on kc.table_name = tc.table_name
|
||||||
|
@ -69,9 +70,11 @@ class PostgresPlus extends Sql {
|
||||||
where tc.constraint_type = 'PRIMARY KEY';
|
where tc.constraint_type = 'PRIMARY KEY';
|
||||||
`
|
`
|
||||||
|
|
||||||
constructor(config) {
|
constructor(config, datasource) {
|
||||||
super("pg")
|
super("pg")
|
||||||
this.config = config
|
this.config = config
|
||||||
|
this.datasource = datasource
|
||||||
|
|
||||||
if (!this.pool) {
|
if (!this.pool) {
|
||||||
this.pool = new Pool(this.config)
|
this.pool = new Pool(this.config)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +104,8 @@ class PostgresPlus extends Sql {
|
||||||
// table key doesn't exist yet
|
// table key doesn't exist yet
|
||||||
if (!tables[tableName]) {
|
if (!tables[tableName]) {
|
||||||
tables[tableName] = {
|
tables[tableName] = {
|
||||||
_id: `${datasourceId}_${tableName}`,
|
_id: `${datasourceId}${SEPARATOR}${tableName}`,
|
||||||
|
// TODO: this needs to accommodate composite keys
|
||||||
primary: keys,
|
primary: keys,
|
||||||
name: tableName,
|
name: tableName,
|
||||||
schema: {},
|
schema: {},
|
||||||
|
|
Loading…
Reference in New Issue