import frappe from frappe import _ from frappe.utils import cint, flt from frappe.database.schema import DBTable, get_definition class PostgresTable(DBTable): def create(self): add_text = '' # columns column_defs = self.get_column_definitions() if column_defs: add_text += ',\n'.join(column_defs) # index # index_defs = self.get_index_definitions() # TODO: set docstatus length # create table frappe.db.sql("""create table `%s` ( name varchar({varchar_len}) not null primary key, creation timestamp(6), modified timestamp(6), modified_by varchar({varchar_len}), owner varchar({varchar_len}), docstatus smallint not null default '0', parent varchar({varchar_len}), parentfield varchar({varchar_len}), parenttype varchar({varchar_len}), idx bigint not null default '0', %s)""".format(varchar_len=frappe.db.VARCHAR_LEN) % (self.table_name, add_text)) frappe.db.commit() def alter(self): for col in self.columns.values(): col.build_for_alter_table(self.current_columns.get(col.fieldname.lower())) query = [] for col in self.add_column: query.append("ADD COLUMN `{}` {}".format(col.fieldname, col.get_definition())) for col in self.change_type: query.append("ALTER COLUMN `{}` TYPE {}".format(col.fieldname, get_definition(col.fieldtype, precision=col.precision, length=col.length))) for col in self.set_default: if col.fieldname=="name": continue if col.fieldtype in ("Check", "Int"): col_default = cint(col.default) elif col.fieldtype in ("Currency", "Float", "Percent"): col_default = flt(col.default) elif not col.default: col_default = "NULL" else: col_default = "{}".format(frappe.db.escape(col.default)) query.append("ALTER COLUMN `{}` SET DEFAULT {}".format(col.fieldname, col_default)) create_index_query = "" for col in self.add_index: # if index key not exists create_index_query += 'CREATE INDEX IF NOT EXISTS "{index_name}" ON `{table_name}`(`{field}`);'.format( index_name=col.fieldname, table_name=self.table_name, field=col.fieldname) drop_index_query = "" for col in self.drop_index: # primary key if col.fieldname != 'name': # if index key exists if not frappe.db.has_index(self.table_name, col.fieldname): drop_index_query += 'DROP INDEX IF EXISTS "{}" ;'.format(col.fieldname) if query: try: final_alter_query = "ALTER TABLE `{}` {}".format(self.table_name, ", ".join(query)) if final_alter_query: frappe.db.sql(final_alter_query) if create_index_query: frappe.db.sql(create_index_query) if drop_index_query: frappe.db.sql(drop_index_query) except Exception as e: # sanitize if frappe.db.is_duplicate_fieldname(e): frappe.throw(str(e)) elif frappe.db.is_duplicate_entry(e): fieldname = str(e).split("'")[-2] frappe.throw(_("""{0} field cannot be set as unique in {1}, as there are non-unique existing values""".format( fieldname, self.table_name))) raise e else: raise e