Liquibase:变更集自动生成 ID
Liquibase: changeset auto generate ID
如何使用 liquibase 自动生成变更集 ID?
我不想手动设置每个变更集的 ID,有没有办法自动设置?
我认为生成的 ID 不是个好主意。原因是 liquibase 使用 changeSet id 来计算校验和(除了作者和文件名)。所以如果你在其他人之间插入一个 changeSet,所有后续 changeSet 的校验和都会改变,你会得到大量的 warnings/errors。
无论如何,如果您仍然想生成 ID,我可以想到这些解决方案:
- 创建你自己的ChangeLogParser
如果您自己解析 ChangeLog,您可以随意生成您想要的 ID。
缺点是您必须为更改日志提供自定义 Xml 架构。来自 Liquibase 的模式对 changeSet id 有限制(必需)。使用新模式,您可能必须对解析器进行大量调整。
或者,您可以选择另一种 changeLog 格式(YAML、JSON、Groovy)。他们的解析器可能更容易定制,因为他们不需要该架构定义。
- 做一些预处理
您可以编写一个简单的 xslt(Xml 转换),从具有 none.
的文件生成带有 changeSet id 的 changeLog
- 使用时间戳作为 ID
这是我的建议。它并没有按照您提出的方式解决问题,但它简单、一致,提供了额外的信息,对于其他数据库迁移工具也是一种很好的做法 http://www.jeremyjarrell.com/using-flyway-db-with-distributed-version-control/
我写了一个 Python 脚本来生成唯一的 ID 到 Liquibase 更新日志中。
小心!
DO 生成 ID
- 更新日志正在开发或准备发布时
- 或者当你控制目标数据库的校验和时
不要生成 ID
- 当变更日志已经部署时
"""
###############################################################################
Purpose: Generate unique subsequent IDs into Liquibase changelogs
###############################################################################
Args:
param1: Full Windows path changelog directory (optional)
OR
--inplace: directly process changelogs (optional)
By default, XML files in the current directory are processed.
Returns:
In case of success, the output path is returned to stdout.
Otherwise, we crash and drag the system into mordor.
If you feel like wasting time you can:
a) port path handling to *nix
b) handle any obscure exceptions
c) add Unicode support (for better entertainment)
Dependencies:
Besides Python 3, in order to preserve XML comments, I had to use lxml
instead of the stock ElementTree parser.
Install lxml:
$ pip install lxml
Proxy clusterfuck? Don't panic! Simply download a .whl package from:
https://pypi.org/project/lxml/#files and install with pip.
Bugs:
Changesets having id="0" are ignored. Usually, these do not occur.
Author:
Tobias Bräutigam
Versions:
0.0.1 - re based, deprecated
0.0.2 - parse XML with lxml, CURRENT
"""
import datetime
import sys
import os
from pathlib import Path, PureWindowsPath
try:
import lxml.etree as ET
except ImportError as error:
print ('''
Error: module lxml is missing.
Please install it:
pip install lxml
''')
exit()
# Process arguments
prefix = '' # hold separator, if needed
outdir = 'out'
try: sys.argv[1]
except: pass
else:
if sys.argv[1] == '--inplace':
outdir = ''
else:
prefix = outdir + '//'
# accept Windows path syntax
inpath = PureWindowsPath(sys.argv[1])
# convert path format
inpath = Path(inpath)
os.chdir(inpath)
try: os.mkdir(outdir)
except: pass
filelist = [ f for f in os.listdir(outdir) ]
for f in filelist: os.remove(os.path.join(outdir, f))
# Parse XML, generate IDs, write file
def parseX(filename,prefix):
cnt = 0
print (filename)
tree = ET.parse(filename)
for node in tree.getiterator():
if int(node.attrib.get('id', 0)):
now = datetime.datetime.now()
node.attrib['id'] = str(int(now.strftime("%H%M%S%f"))+cnt*37)
cnt = cnt + 1
root = tree.getroot()
# NS URL element name is '' for Etree, lxml requires at least one character
ET.register_namespace('x', u'http://www.liquibase.org/xml/ns/dbchangelog')
tree = ET.ElementTree(root)
tree.write(prefix + filename, encoding='utf-8', xml_declaration=True)
print(str(cnt) +' ID(s) generated.')
# Process files
print('\n')
items = 0
for infile in os.listdir('.'):
if (infile.lower().endswith('.xml')) == True:
parseX(infile,prefix)
items=items+1
# Message
print('\n' + str(items) + ' file(s) processed.\n\n')
if items > 0:
print('Output was written to: \n\n')
print(str(os.getcwd()) + '\' + outdir + '\n')
如何使用 liquibase 自动生成变更集 ID?
我不想手动设置每个变更集的 ID,有没有办法自动设置?
我认为生成的 ID 不是个好主意。原因是 liquibase 使用 changeSet id 来计算校验和(除了作者和文件名)。所以如果你在其他人之间插入一个 changeSet,所有后续 changeSet 的校验和都会改变,你会得到大量的 warnings/errors。
无论如何,如果您仍然想生成 ID,我可以想到这些解决方案:
- 创建你自己的ChangeLogParser
如果您自己解析 ChangeLog,您可以随意生成您想要的 ID。 缺点是您必须为更改日志提供自定义 Xml 架构。来自 Liquibase 的模式对 changeSet id 有限制(必需)。使用新模式,您可能必须对解析器进行大量调整。 或者,您可以选择另一种 changeLog 格式(YAML、JSON、Groovy)。他们的解析器可能更容易定制,因为他们不需要该架构定义。
- 做一些预处理
您可以编写一个简单的 xslt(Xml 转换),从具有 none.
的文件生成带有 changeSet id 的 changeLog- 使用时间戳作为 ID
这是我的建议。它并没有按照您提出的方式解决问题,但它简单、一致,提供了额外的信息,对于其他数据库迁移工具也是一种很好的做法 http://www.jeremyjarrell.com/using-flyway-db-with-distributed-version-control/
我写了一个 Python 脚本来生成唯一的 ID 到 Liquibase 更新日志中。
小心!
DO 生成 ID
- 更新日志正在开发或准备发布时
- 或者当你控制目标数据库的校验和时
不要生成 ID - 当变更日志已经部署时
"""
###############################################################################
Purpose: Generate unique subsequent IDs into Liquibase changelogs
###############################################################################
Args:
param1: Full Windows path changelog directory (optional)
OR
--inplace: directly process changelogs (optional)
By default, XML files in the current directory are processed.
Returns:
In case of success, the output path is returned to stdout.
Otherwise, we crash and drag the system into mordor.
If you feel like wasting time you can:
a) port path handling to *nix
b) handle any obscure exceptions
c) add Unicode support (for better entertainment)
Dependencies:
Besides Python 3, in order to preserve XML comments, I had to use lxml
instead of the stock ElementTree parser.
Install lxml:
$ pip install lxml
Proxy clusterfuck? Don't panic! Simply download a .whl package from:
https://pypi.org/project/lxml/#files and install with pip.
Bugs:
Changesets having id="0" are ignored. Usually, these do not occur.
Author:
Tobias Bräutigam
Versions:
0.0.1 - re based, deprecated
0.0.2 - parse XML with lxml, CURRENT
"""
import datetime
import sys
import os
from pathlib import Path, PureWindowsPath
try:
import lxml.etree as ET
except ImportError as error:
print ('''
Error: module lxml is missing.
Please install it:
pip install lxml
''')
exit()
# Process arguments
prefix = '' # hold separator, if needed
outdir = 'out'
try: sys.argv[1]
except: pass
else:
if sys.argv[1] == '--inplace':
outdir = ''
else:
prefix = outdir + '//'
# accept Windows path syntax
inpath = PureWindowsPath(sys.argv[1])
# convert path format
inpath = Path(inpath)
os.chdir(inpath)
try: os.mkdir(outdir)
except: pass
filelist = [ f for f in os.listdir(outdir) ]
for f in filelist: os.remove(os.path.join(outdir, f))
# Parse XML, generate IDs, write file
def parseX(filename,prefix):
cnt = 0
print (filename)
tree = ET.parse(filename)
for node in tree.getiterator():
if int(node.attrib.get('id', 0)):
now = datetime.datetime.now()
node.attrib['id'] = str(int(now.strftime("%H%M%S%f"))+cnt*37)
cnt = cnt + 1
root = tree.getroot()
# NS URL element name is '' for Etree, lxml requires at least one character
ET.register_namespace('x', u'http://www.liquibase.org/xml/ns/dbchangelog')
tree = ET.ElementTree(root)
tree.write(prefix + filename, encoding='utf-8', xml_declaration=True)
print(str(cnt) +' ID(s) generated.')
# Process files
print('\n')
items = 0
for infile in os.listdir('.'):
if (infile.lower().endswith('.xml')) == True:
parseX(infile,prefix)
items=items+1
# Message
print('\n' + str(items) + ' file(s) processed.\n\n')
if items > 0:
print('Output was written to: \n\n')
print(str(os.getcwd()) + '\' + outdir + '\n')