mirror of
https://github.com/frappe/books.git
synced 2025-01-22 14:48:25 +00:00
foreign keys
This commit is contained in:
parent
61294fd77f
commit
742b933207
@ -30,54 +30,90 @@ module.exports = class Database extends Observable {
|
||||
await this.commit();
|
||||
}
|
||||
|
||||
async createTable(doctype) {
|
||||
async createTable(doctype, newName=null) {
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let columns = [];
|
||||
let values = [];
|
||||
let indexes = [];
|
||||
|
||||
for (let field of meta.getValidFields({ withChildren: false })) {
|
||||
if (this.type_map[field.fieldtype]) {
|
||||
columns.push(this.getColumnDefinition(field));
|
||||
this.updateColumnDefinition(field, columns, indexes);
|
||||
}
|
||||
}
|
||||
|
||||
return await this.runCreateTableQuery(doctype, columns, values);
|
||||
return await this.runCreateTableQuery(newName || doctype, columns, indexes);
|
||||
}
|
||||
|
||||
async tableExists(table) {
|
||||
// return true if table exists
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, values) {
|
||||
async runCreateTableQuery(doctype, columns, indexes) {
|
||||
// override
|
||||
}
|
||||
|
||||
getColumnDefinition(df) {
|
||||
updateColumnDefinition(field, columns, indexes) {
|
||||
// return `${df.fieldname} ${this.type_map[df.fieldtype]} ${ ? "PRIMARY KEY" : ""} ${df.required && !df.default ? "NOT NULL" : ""} ${df.default ? `DEFAULT ${df.default}` : ""}`
|
||||
}
|
||||
|
||||
async alterTable(doctype) {
|
||||
// get columns
|
||||
let newColumns = await this.getNewColumns(doctype);
|
||||
let newForeignKeys = await this.getNewForeignKeys(doctype);
|
||||
|
||||
if (newColumns.length) {
|
||||
await this.addColumns(doctype, newColumns);
|
||||
}
|
||||
if (newForeignKeys.length) {
|
||||
await this.addForeignKeys(doctype);
|
||||
}
|
||||
}
|
||||
|
||||
async getNewColumns(doctype) {
|
||||
let tableColumns = await this.getTableColumns(doctype);
|
||||
let meta = frappe.getMeta(doctype);
|
||||
let values = [];
|
||||
|
||||
let newColumns = [];
|
||||
for (let field of meta.getValidFields({ withChildren: false })) {
|
||||
if (!tableColumns.includes(field.fieldname) && this.type_map[field.fieldtype]) {
|
||||
values = []
|
||||
if (field.default) {
|
||||
values.push(field.default);
|
||||
}
|
||||
await this.runAlterTableQuery(doctype, field, values);
|
||||
newColumns.push(field);
|
||||
}
|
||||
}
|
||||
return newColumns;
|
||||
}
|
||||
|
||||
async addColumns(doctype, newColumns) {
|
||||
for (let field of newColumns) {
|
||||
await this.runAddColumnQuery(doctype, field);
|
||||
}
|
||||
}
|
||||
|
||||
async getNewForeignKeys(doctype) {
|
||||
let foreignKeys = await this.getForeignKeys(doctype);
|
||||
let newForeignKeys = [];
|
||||
let meta = frappe.getMeta(doctype);
|
||||
for (let field of meta.getValidFields({ withChildren: false})) {
|
||||
if (field.fieldtype==='Link' && !foreignKeys.includes(field.fieldname)) {
|
||||
newForeignKeys.push(field);
|
||||
}
|
||||
}
|
||||
return newForeignKeys;
|
||||
}
|
||||
|
||||
async addForeignKeys(doctype, newForeignKeys) {
|
||||
for (let field of newForeignKeys) {
|
||||
this.addForeignKey(doctype, field);
|
||||
}
|
||||
}
|
||||
|
||||
async getForeignKey(doctype, field) {
|
||||
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async runAlterTableQuery(doctype, field, values) {
|
||||
async runAddColumnQuery(doctype, field) {
|
||||
// alter table {doctype} add column ({column_def});
|
||||
}
|
||||
|
||||
|
@ -52,8 +52,8 @@ module.exports = class mysqlDatabase extends Database{
|
||||
}
|
||||
|
||||
|
||||
getColumnDefinition(df) {
|
||||
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${df.reqd && !df.default ? "not null" : ""} ${df.default ? `default '${df.default}'` : ""}`
|
||||
updateColumnDefinition(df, columns, indexes) {
|
||||
columns.push(`${df.fieldname} ${this.type_map[df.fieldtype]} ${df.reqd && !df.default ? "not null" : ""} ${df.default ? `default '${df.default}'` : ""}`);
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
@ -61,7 +61,7 @@ module.exports = class mysqlDatabase extends Database{
|
||||
}
|
||||
|
||||
|
||||
async runAlterTableQuery(doctype) {
|
||||
async runAddColumnQuery(doctype) {
|
||||
await this.run(`ALTER TABLE ${doctype} ADD COLUMN ${this.get_column_definition(df)}`, values);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ module.exports = class sqliteDatabase extends Database {
|
||||
if (debug) {
|
||||
this.conn.on('trace', (trace) => console.log(trace));
|
||||
}
|
||||
resolve();
|
||||
this.run('PRAGMA foreign_keys=ON').then(resolve);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -28,22 +28,70 @@ module.exports = class sqliteDatabase extends Database {
|
||||
return (name && name.length) ? true : false;
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, values) {
|
||||
const query = `CREATE TABLE IF NOT EXISTS ${doctype} (
|
||||
${columns.join(", ")})`;
|
||||
async alterTable(doctype) {
|
||||
let newColumns = await this.getNewColumns(doctype);
|
||||
let newForeignKeys = await this.getNewForeignKeys(doctype);
|
||||
|
||||
return await this.run(query, values);
|
||||
if (newColumns.length || newForeignKeys.length) {
|
||||
await this.migrateToNewTable(doctype);
|
||||
}
|
||||
}
|
||||
|
||||
getColumnDefinition(df) {
|
||||
return `${df.fieldname} ${this.type_map[df.fieldtype]} ${ df.fieldname==="name" ? "PRIMARY KEY" : ""} ${df.required && !df.default ? "NOT NULL" : ""} ${df.default ? `DEFAULT ${df.default}` : ""}`
|
||||
async migrateToNewTable(doctype) {
|
||||
await this.run('PRAGMA foreign_keys=OFF');
|
||||
await this.run('BEGIN TRANSACTION');
|
||||
|
||||
// create temp table
|
||||
await this.createTable(doctype, 'TEMP' + doctype);
|
||||
|
||||
// copy from old to new table
|
||||
await this.run(`INSERT INTO TEMP${doctype} SELECT * from ${doctype}`);
|
||||
|
||||
// drop old table
|
||||
await this.run(`DROP TABLE ${doctype}`);
|
||||
|
||||
// rename new table
|
||||
await this.run(`ALTER TABLE TEMP${doctype} RENAME TO ${doctype}`);
|
||||
|
||||
await this.run('COMMIT');
|
||||
await this.run('PRAGMA foreign_keys=ON');
|
||||
}
|
||||
|
||||
async runCreateTableQuery(doctype, columns, indexes) {
|
||||
const query = `CREATE TABLE IF NOT EXISTS ${doctype} (
|
||||
${columns.join(", ")} ${indexes.length ? (", " + indexes.join(", ")) : ''})`;
|
||||
|
||||
return await this.run(query);
|
||||
}
|
||||
|
||||
updateColumnDefinition(field, columns, indexes) {
|
||||
let def = `${field.fieldname} ${this.type_map[field.fieldtype]}`;
|
||||
if (field.fieldname==='name') {
|
||||
def += ' PRIMARY KEY NOT NULL';
|
||||
}
|
||||
else if (field.reqd) {
|
||||
def += ' NOT NULL';
|
||||
}
|
||||
if (field.default) {
|
||||
def += `DEFAULT ${field.default}`;
|
||||
}
|
||||
|
||||
columns.push(def);
|
||||
|
||||
if (field.fieldtype==='Link' && field.target) {
|
||||
indexes.push(`FOREIGN KEY (${field.fieldname}) REFERENCES ${field.target} ON UPDATE RESTRICT ON DELETE RESTRICT`);
|
||||
}
|
||||
}
|
||||
|
||||
async getTableColumns(doctype) {
|
||||
return (await this.sql(`PRAGMA table_info(${doctype})`)).map(d => d.name);
|
||||
}
|
||||
|
||||
async runAlterTableQuery(doctype, field, values) {
|
||||
async getForeignKeys(doctype) {
|
||||
return (await this.sql(`PRAGMA foreign_key_list(${doctype})`)).map(d => d.from);
|
||||
}
|
||||
|
||||
async runAddColumnQuery(doctype, field, values) {
|
||||
await this.run(`ALTER TABLE ${doctype} ADD COLUMN ${this.getColumnDefinition(field)}`, values);
|
||||
}
|
||||
|
||||
|
@ -52,9 +52,7 @@ module.exports = class BaseForm extends Observable {
|
||||
if (!this.meta.isSingle && this.actions.includes('delete')) {
|
||||
let menu = this.container.getDropdown(frappe._('Menu'));
|
||||
menu.addItem(frappe._("Delete"), async (e) => {
|
||||
await this.doc.delete();
|
||||
this.showAlert('Deleted', 'success');
|
||||
this.trigger('delete');
|
||||
await this.delete();
|
||||
});
|
||||
}
|
||||
|
||||
@ -178,6 +176,16 @@ module.exports = class BaseForm extends Observable {
|
||||
await this.trigger('submit');
|
||||
}
|
||||
|
||||
async delete() {
|
||||
try {
|
||||
await this.doc.delete();
|
||||
this.showAlert('Deleted', 'success');
|
||||
this.trigger('delete');
|
||||
} catch (e) {
|
||||
this.showAlert(e, 'danger');
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
for(let control of this.controlList) {
|
||||
control.refresh();
|
||||
|
@ -133,7 +133,7 @@ module.exports = class BaseDocument extends Observable {
|
||||
this.owner = frappe.session.user;
|
||||
this.creation = now;
|
||||
}
|
||||
this.modified_by = frappe.session.user;
|
||||
this.modifieldBy = frappe.session.user;
|
||||
this.modified = now;
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,10 @@ module.exports = {
|
||||
],
|
||||
parent_fields: [
|
||||
{
|
||||
fieldname: 'owner', fieldtype: 'Link', required: 1, options: 'User'
|
||||
fieldname: 'owner', fieldtype: 'Text', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'modified_by', fieldtype: 'Link', required: 1, options: 'User'
|
||||
fieldname: 'modifieldBy', fieldtype: 'Text', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'creation', fieldtype: 'Datetime', required: 1
|
||||
@ -48,7 +48,7 @@ module.exports = {
|
||||
fieldname: 'parent', fieldtype: 'Data', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'parenttype', fieldtype: 'Link', required: 1, options: 'DocType'
|
||||
fieldname: 'parenttype', fieldtype: 'Text', required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'parentfield', fieldtype: 'Data', required: 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user