[fix] rename custom fields before sync if name conflicts (#5062)

* [fix] rename custom fields before sync if name conflicts

* [minor] re-add text_type

* Update doctype.py
This commit is contained in:
Rushabh Mehta 2018-02-23 11:10:21 +05:30 committed by Nabin Hait
parent c06dfafd99
commit f20da41bf6
4 changed files with 42 additions and 9 deletions

View file

@ -15,7 +15,7 @@ from frappe.model.document import Document
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.desk.notifications import delete_notification_count_for
from frappe.modules import make_boilerplate
from frappe.model.db_schema import validate_column_name, validate_column_length
from frappe.model.db_schema import validate_column_name, validate_column_length, type_map
import frappe.website.render
# imports - third-party imports
@ -205,6 +205,8 @@ class DocType(Document):
def on_update(self):
"""Update database schema, make controller templates if `custom` is not set and clear cache."""
from frappe.model.db_schema import updatedb
self.rename_custom_fields()
updatedb(self.name, self)
self.change_modified_of_parent()
@ -236,6 +238,28 @@ class DocType(Document):
if self.name in frappe.local.meta_cache:
del frappe.local.meta_cache[self.name]
def rename_custom_fields(self):
if not (frappe.db.table_exists(self.name) and frappe.db.table_exists("Custom Field")):
return
fields = [d.fieldname for d in self.fields if d.fieldtype in type_map]
custom_field_conflict = frappe.db.sql('''select name, fieldname from
`tabCustom Field`
where
fieldname in ({0})'''.format(', '.join(['%s'] * len(fields))), fields, as_dict=True)
for custom_field in custom_field_conflict:
if frappe.db.has_column(self.name, custom_field.fieldname):
frappe.db.commit()
column_type = frappe.db.get_column_type(self.name, custom_field.fieldname)
if not frappe.db.has_column(self.name, custom_field.fieldname + '_custom'):
frappe.db.sql('alter table `tab{0}` change `{1}` `{1}_custom` {2}'.format(self.name,
custom_field.fieldname, column_type))
# rename in custom field
frappe.db.set_value('Custom Field', custom_field.name, 'fieldname', custom_field.fieldname + '_custom')
def sync_global_search(self):
'''If global search settings are changed, rebuild search properties for this table'''
global_search_fields_before_update = [d.fieldname for d in

View file

@ -776,9 +776,9 @@ class Database:
"""Return true of field exists."""
return self.sql("select name from tabDocField where fieldname=%s and parent=%s", (dt, fn))
def table_exists(self, tablename):
"""Returns True if table exists."""
return ("tab" + tablename) in self.get_tables()
def table_exists(self, doctype):
"""Returns True if table for given doctype exists."""
return ("tab" + doctype) in self.get_tables()
def get_tables(self):
return [d[0] for d in self.sql("show tables")]
@ -842,6 +842,10 @@ class Database:
"""Returns True if column exists in database."""
return column in self.get_table_columns(doctype)
def get_column_type(self, doctype, column):
return frappe.db.sql('''SELECT column_type FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tab{0}' AND COLUMN_NAME = "{1}"'''.format(doctype, column))[0][0]
def add_index(self, doctype, fields, index_name=None):
"""Creates an index with given fields if not already created.
Index name will be `fieldname1_fieldname2_index`"""

View file

@ -352,7 +352,10 @@ def sync_from_app(app):
m['_doctype'] = m.pop('doctype')
desktop_icon.update(m)
desktop_icon.save()
try:
desktop_icon.save()
except frappe.exceptions.UniqueValidationError:
pass
return modules_list

View file

@ -15,6 +15,8 @@ from bs4 import BeautifulSoup
import jinja2.exceptions
from six import text_type
import io
def sync():
# make table
print('Syncing help database...')
@ -55,7 +57,7 @@ class HelpDatabase(object):
self.global_help_setup = frappe.conf.get('global_help_setup')
if self.global_help_setup:
bench_name = os.path.basename(os.path.abspath(frappe.get_app_path('frappe')).split('/apps/')[0])
self.help_db_name = hashlib.sha224(bench_name).hexdigest()[:15]
self.help_db_name = hashlib.sha224(bench_name.encode('utf-8')).hexdigest()[:15]
def make_database(self):
'''make database for global help setup'''
@ -135,9 +137,9 @@ class HelpDatabase(object):
for fname in files:
if fname.rsplit('.', 1)[-1] in ('md', 'html'):
fpath = os.path.join(basepath, fname)
with open(fpath, 'r') as f:
with io.open(fpath, 'r', encoding = 'utf-8') as f:
try:
content = frappe.render_template(text_type(f.read(), 'utf-8'),
content = frappe.render_template(f.read(),
{'docs_base_url': '/assets/{app}_docs'.format(app=app)})
relpath = self.get_out_path(fpath)
@ -235,7 +237,7 @@ class HelpDatabase(object):
# files not in index.txt
for f in os.listdir(path):
if not os.path.isdir(os.path.join(path, f)):
if not os.path.isdir(os.path.join(path, f)) and len(f.rsplit('.', 1)) == 2:
name, extn = f.rsplit('.', 1)
if name not in files \
and name != 'index' and extn in ('md', 'html'):