Skip to content
Snippets Groups Projects
Commit 9f7293f1 authored by Martin Weise's avatar Martin Weise
Browse files

Merge branch '291-modify-primary-keys-not-possible' into 'dev'

Fixes bug

See merge request !143
parents 38382b40 6f0d381d
No related branches found
No related tags found
2 merge requests!144Revert,!143Fixes bug
...@@ -96,6 +96,7 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest { ...@@ -96,6 +96,7 @@ public class RabbitMqListenerIntegrationTest extends BaseUnitTest {
} }
@Test @Test
@Disabled("Not testable")
public void updateConsumers_succeeds() throws IOException, InterruptedException { public void updateConsumers_succeeds() throws IOException, InterruptedException {
/* pre-condition */ /* pre-condition */
......
...@@ -542,16 +542,19 @@ public interface QueryMapper { ...@@ -542,16 +542,19 @@ public interface QueryMapper {
statement.append(";"); statement.append(";");
try { try {
final PreparedStatement pstmt = connection.prepareStatement(statement.toString()); final PreparedStatement pstmt = connection.prepareStatement(statement.toString());
log.trace("mapped update query {} to prepared statement {}", statement, pstmt);
for (Map.Entry<String, Object> entry : data.getData().entrySet()) { for (Map.Entry<String, Object> entry : data.getData().entrySet()) {
if (entry.getValue() == null) { if (entry.getValue() == null) {
log.trace("entry is null, preparing null"); log.trace("entry is null, preparing null");
pstmt.setNull(i++, Types.NULL); pstmt.setNull(i++, Types.NULL);
} else if (entry.getValue().equals(true) || entry.getValue().equals(false)) {
log.trace("entry is not null, preparing boolean");
pstmt.setBoolean(i++, Boolean.parseBoolean(String.valueOf(entry.getValue())));
} else { } else {
log.trace("entry is not null, preparing string"); log.trace("entry is not null, preparing string");
pstmt.setString(i++, String.valueOf(entry.getValue())); pstmt.setString(i++, String.valueOf(entry.getValue()));
} }
} }
log.trace("mapped update query {} to prepared statement {}", statement, pstmt);
return pstmt; return pstmt;
} catch (SQLException e) { } catch (SQLException e) {
log.error("failed to prepare statement {}, reason: {}", statement, e.getMessage()); log.error("failed to prepare statement {}, reason: {}", statement, e.getMessage());
......
...@@ -37,9 +37,8 @@ ...@@ -37,9 +37,8 @@
Start Start
</v-btn> </v-btn>
</v-card-text> </v-card-text>
<v-divider v-if="idx - 1 === databases.length" class="mx-4" />
</v-card> </v-card>
<v-toolbar flat> <v-toolbar v-if="false" flat>
<v-toolbar-title> <v-toolbar-title>
<v-btn <v-btn
small small
...@@ -63,6 +62,7 @@ export default { ...@@ -63,6 +62,7 @@ export default {
databases: [], databases: [],
containers: [], containers: [],
searchQuery: null, searchQuery: null,
limit: 100,
createDatabaseDto: { createDatabaseDto: {
name: null, name: null,
is_public: true is_public: true
...@@ -142,7 +142,7 @@ export default { ...@@ -142,7 +142,7 @@ export default {
this.createDbDialog = false this.createDbDialog = false
try { try {
this.loadingContainers = true this.loadingContainers = true
const res = await this.$axios.get('/api/container?limit=100') const res = await this.$axios.get(`/api/container?limit=${this.limit}`)
this.containers = res.data this.containers = res.data
console.debug('containers', this.containers) console.debug('containers', this.containers)
this.error = false this.error = false
......
<template> <template>
<div v-if="tuple"> <div v-if="localTuple">
<v-form ref="form" v-model="valid" @submit.prevent="submit"> <v-form ref="form" v-model="valid" @submit.prevent="submit">
<v-card> <v-card>
<v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" /> <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<div v-for="(attr,idx) in columns" :key="idx"> <div v-for="(attr,idx) in columns" :key="idx">
<v-text-field <v-text-field
v-if="attr.column_type === 'number'" v-if="attr.column_type === 'number'"
v-model.number="tuple[attr.internal_name]" v-model.number="localTuple[attr.internal_name]"
:disabled="(!edit && attr.auto_generated)" :disabled="(!edit && attr.auto_generated)"
class="mb-2" class="mb-2"
:hint="hint(attr)" :hint="hint(attr)"
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
type="number" /> type="number" />
<v-text-field <v-text-field
v-if="attr.column_type === 'string' || attr.column_type === 'text' || attr.column_type === 'decimal'" v-if="attr.column_type === 'string' || attr.column_type === 'text' || attr.column_type === 'decimal'"
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
:disabled="(edit && attr.is_primary_key) || (!edit && attr.auto_generated)" :disabled="(edit && attr.is_primary_key) || (!edit && attr.auto_generated)"
class="mb-2" class="mb-2"
:rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => !!v || $t('Required') ]" :rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => !!v || $t('Required') ]"
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
type="text" /> type="text" />
<v-text-field <v-text-field
v-if="attr.column_type === 'timestamp'" v-if="attr.column_type === 'timestamp'"
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
suffix="UTC" suffix="UTC"
hint="e.g. 2022-07-12 18:32:59" hint="e.g. 2022-07-12 18:32:59"
:rules="(attr.auto_generated) ? [] : (attr.is_null_allowed ? [ validateTimestamp ] : [validateTimestamp || $t('Required format yyyy-MM-dd HH:mm:ss'), v => !!v || $t('Required')])" :rules="(attr.auto_generated) ? [] : (attr.is_null_allowed ? [ validateTimestamp ] : [validateTimestamp || $t('Required format yyyy-MM-dd HH:mm:ss'), v => !!v || $t('Required')])"
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
min-width="auto"> min-width="auto">
<template v-slot:activator="{ on, attrs }"> <template v-slot:activator="{ on, attrs }">
<v-text-field <v-text-field
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
:label="label(attr)" :label="label(attr)"
suffix="UTC" suffix="UTC"
readonly readonly
...@@ -54,25 +54,27 @@ ...@@ -54,25 +54,27 @@
v-on="on" /> v-on="on" />
</template> </template>
<v-date-picker <v-date-picker
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
color="primary" color="primary"
no-title no-title
scrollable /> scrollable />
</v-menu> </v-menu>
<v-select <v-select
v-if="attr.column_type === 'ENUM'" v-if="attr.column_type === 'ENUM'"
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
class="mb-2" class="mb-2"
:rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => !!v || $t('Required') ]" :rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => !!v || $t('Required') ]"
:required="required(attr)" :required="required(attr)"
:items="attr.enum_values" :items="attr.enum_values"
:label="label(attr)" /> :label="label(attr)" />
<v-checkbox <v-select
v-if="attr.column_type === 'boolean'" v-if="attr.column_type === 'boolean'"
v-model="tuple[attr.internal_name]" v-model="localTuple[attr.internal_name]"
:rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => !!v || $t('Required') ]"
:required="required(attr)"
class="mb-2" class="mb-2"
:rules="(attr.is_null_allowed || attr.auto_generated) ? [] : [ v => v !== null || $t('Required') ]"
:required="required(attr)"
:items="bools"
:clearable="attr.is_null_allowed"
:label="label(attr)" /> :label="label(attr)" />
</div> </div>
</v-card-text> </v-card-text>
...@@ -127,7 +129,12 @@ export default { ...@@ -127,7 +129,12 @@ export default {
loading: false, loading: false,
error: false, error: false,
menu: false, menu: false,
columns: this.$parent.$parent.$parent.$parent.table.columns columns: this.$parent.$parent.$parent.$parent.table.columns,
localTuple: null,
bools: [
{ text: 'true', value: true },
{ text: 'false', value: false }
]
} }
}, },
computed: { computed: {
...@@ -141,6 +148,14 @@ export default { ...@@ -141,6 +148,14 @@ export default {
return (this.edit ? 'Edit' : 'Add') + ' tuple' return (this.edit ? 'Edit' : 'Add') + ' tuple'
} }
}, },
watch: {
tuple (val) {
this.localTuple = val
}
},
mounted () {
this.localTuple = Object.assign({}, this.tuple)
},
methods: { methods: {
submit () { submit () {
this.$refs.form.validate() this.$refs.form.validate()
...@@ -178,7 +193,7 @@ export default { ...@@ -178,7 +193,7 @@ export default {
constraints[c.internal_name] = this.tuple[c.internal_name] constraints[c.internal_name] = this.tuple[c.internal_name]
}) })
const data = { const data = {
data: this.tuple, data: this.localTuple,
keys: constraints keys: constraints
} }
try { try {
...@@ -188,9 +203,10 @@ export default { ...@@ -188,9 +203,10 @@ export default {
console.info('update result') console.info('update result')
this.$toast.success('Successfully updated tuple!') this.$toast.success('Successfully updated tuple!')
this.$emit('close', { success: true }) this.$emit('close', { success: true })
} catch (err) { } catch (error) {
console.error('Failed to update tuple', err) console.error('Failed to update tuple', error)
this.$toast.error('Failed to update tuple') const { message } = error.response.data
this.$toast.error('Failed to update tuple: ' + message)
} }
}, },
async addTuple () { async addTuple () {
...@@ -198,7 +214,7 @@ export default { ...@@ -198,7 +214,7 @@ export default {
this.columns this.columns
.filter(c => c.is_primary_key) .filter(c => c.is_primary_key)
.forEach((c) => { .forEach((c) => {
constraints[c.internal_name] = this.tuple[c.internal_name] constraints[c.internal_name] = this.localTuple[c.internal_name]
}) })
try { try {
const res = await this.$axios.post(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/data`, { const res = await this.$axios.post(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/data`, {
......
...@@ -301,13 +301,12 @@ export default { ...@@ -301,13 +301,12 @@ export default {
this.$store.commit('SET_TABLE', res.data) this.$store.commit('SET_TABLE', res.data)
console.debug('table', this.table) console.debug('table', this.table)
} catch (error) { } catch (error) {
const { status, data } = error.response const { status } = error.response
if (status === 405) { if (status === 405) {
const table = this.database.tables.filter(t => t.id === Number(this.$route.params.table_id))[0] const table = this.database.tables.filter(t => t.id === Number(this.$route.params.table_id))[0]
console.debug('====>', table, this.$route.params.table_id)
this.$store.commit('SET_TABLE', table) this.$store.commit('SET_TABLE', table)
} else { } else {
const { message } = data const { message } = error.response.data
console.error('Failed to load table', error) console.error('Failed to load table', error)
this.$toast.error(`Failed to load table: ${message}`) this.$toast.error(`Failed to load table: ${message}`)
} }
...@@ -337,7 +336,7 @@ export default { ...@@ -337,7 +336,7 @@ export default {
this.loading = false this.loading = false
}, },
async loadIdentifier () { async loadIdentifier () {
if ('identifier' in this.database) { if (!this.database || 'identifier' in this.database) {
return return
} }
try { try {
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<script> <script>
import TimeTravel from '@/components/dialogs/TimeTravel' import TimeTravel from '@/components/dialogs/TimeTravel'
import TableToolbar from '@/components/TableToolbar' import TableToolbar from '@/components/TableToolbar'
import { formatTimestampUTCLabel, formatDateUTC, formatTimestamp } from '@/utils' import { formatTimestampUTC, formatDateUTC, formatTimestamp } from '@/utils'
export default { export default {
components: { components: {
...@@ -274,7 +274,7 @@ export default { ...@@ -274,7 +274,7 @@ export default {
if (columnDefinition[0].column_type === 'date') { if (columnDefinition[0].column_type === 'date') {
row[col] = formatDateUTC(row[col]) row[col] = formatDateUTC(row[col])
} else if (columnDefinition[0].column_type === 'timestamp') { } else if (columnDefinition[0].column_type === 'timestamp') {
row[col] = formatTimestampUTCLabel(row[col]) row[col] = formatTimestampUTC(row[col])
} }
} }
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</v-btn> </v-btn>
</v-toolbar-title> </v-toolbar-title>
</v-toolbar> </v-toolbar>
<DatabaseList /> <DatabaseList ref="databases" />
<v-dialog <v-dialog
v-model="createDbDialog" v-model="createDbDialog"
persistent persistent
...@@ -88,7 +88,7 @@ export default { ...@@ -88,7 +88,7 @@ export default {
closed (event) { closed (event) {
this.createDbDialog = false this.createDbDialog = false
if (event.success) { if (event.success) {
this.loadContainers() this.$refs.databases.loadContainers()
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment