Wednesday, November 14, 2012

Eclipse editor for liquibase database change management



             To use eclipse magic auto-complete feature for liquibase change log file editing i defined a xtext grammer and generated a plugin. [ Xtext, an open-source framework for development of programming langauges and domain-specific languages.]

You will see below my xtext grammer for liquibase which just defines some part of its language and also a template of this language to suggest keywords and phrases smartly when using auto complete feature of the Eclipse environment:

Grammer Part:

grammar org.xtext.example.mydsl.Liquibase with org.eclipse.xtext.common.Terminals
generate LiquibaseEditor "http://www.xtext.org/example/mydsl/LiquibaseEditor"
Model:
      (xlists+=Xlist)*;
Xlist:
   '<?xml version="1.0" encoding="UTF-8"?>'
   '<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"'
      'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
      'xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog'
      'http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">'(include+=INCLUDEFILE)*(changeset+=CHANGESET)*'</databaseChangeLog>';
CHANGESET:'<changeSet' 'id='id=STRING 'author='author=STRING(ra=RUNALWAYS)?(roc=RUNONCHANGE)?'>'(pre+=PRECONDITION)?(comment=COMMENT)?((sql+=SQL)|(createProcedure+=CREATEPROCEDURE)|(rb+=ROOLBACK))*'</changeSet>';
 
SQL returns MSQL:
 a=MSQL
;
terminal MSQL:'<sql>'->'</sql>';
MSQLs:'<sql>'=>'</sql>';
INCLUDEFILE:'<include file='fileLocation=STRING'/>';
//SQLFILE:'<sqlFile path='fileLocation=STRING'/>';
RUNALWAYS:'runAlways='ra=BOOLEAN;
RUNONCHANGE:'runOnChange='roc=BOOLEAN;
ROOLBACK returns MROOLBACK:mr=MROOLBACK;
terminal MROOLBACK:'<roolback>'->'</roolback>';
ENDDELIMITER:'endDelimiter='ed=STRING;
STRIPCOMMENTS:'stripComments='sc=BOOLEAN;
SPLITSTATEMENTS:'splitStatements='sps=BOOLEAN;
PRECONDITION:'<preConditions'prect=PRECONDITIONTYPE'>'(sqlCheck+=SQLCHECK)'</preConditions>';
SQLCHECK returns MSQLCHECK:
 b=MSQLCHECK
;
//SQLCHECK:'<sqlCheck expectedResult='EXPECTEDRESULT'>'(sqlStatement+=STRING)'</sqlCheck>';
 
terminal MSQLCHECK:'<sqlCheck expectedResult='STRING'>'->'</sqlCheck>';
//ANDLOGICALEXP:(ab=ENDBTAG)((s+=SQLCHECK)|(ole+=ORLOGICALEXP)|(ale+=ANDLOGICALEXP))*(ae=ENDETAG);
//ORLOGICALEXP:(ob=ORBTAG)((s+=SQLCHECK)|(ole+=ORLOGICALEXP)|(ale+=ANDLOGICALEXP))*(oe=ORETAG);
//ANDLOGIC:'<and>''</and>';
//ORLOGIC:'<or>''</or>';
//ENDBTAG:'<and>';
//ENDETAG:'</and>';
//ORBTAG:'<or>';
//ORETAG:'</or>';
 
PRECONDITIONTYPE:(u=ONUPDATE)|(f=ONFAIL)|(e=ONERROR)|(fm=ONFAILMESSAGE)|(em=ONERRORMESSAGE);
ONUPDATE:'onUpdate='((o='"RUN"')|(o='"FAIL"')|(o='"IGNORE"'));
ONFAIL:'onFail='onFailAttribute=ONFAILERRORTYPEATTRIBUTE;
ONERROR:'onError='onFailAttribute=ONFAILERRORTYPEATTRIBUTE;
ONFAILERRORTYPEATTRIBUTE:(a='"HALT"')|(a='"CONTINUE"')|(a='"MARK_RAN"')|(a='"WARN"');
ONFAILMESSAGE:'onFailMessage='message=STRING;
ONERRORMESSAGE:'onErrorMessage='essage=STRING;
COMMENT:'<comment>'comment=STRING'</comment>';//Comments should go after preCondition. If they are before then liquibase usually gives error.
DROPTABLE:'<dropTable tableName="'tableName=STRING'/>';
 
//~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
//CREATEPROCEDURE:'<createProcedure>'createProcedure=STRING'</createProcedure>';
CREATEPROCEDURE returns MCREATEPROCEDURE:
 b=MCREATEPROCEDURE;
 
terminal MCREATEPROCEDURE:'<createProcedure>'->'</createProcedure>';
/*MERGECOLUMNS:'<mergeColumns tableName="'tableName=STRING
 'column1Name='column1Name=STRING
 'joinString='joinString=STRING
 'column2Name'column2Name=STRING
 'finalColumnName'finalColumnName=STRING
 'finalColumnType'finalColumnType=STRING
;*/
//ADDCOLUMN:'<addColumn tableName='tableName=STRING'>'column=COLUMN'</addColumn>';
//COLUMN:'<column name='columnName=STRING'type='type=STRING'/>';
//Types
BOOLEAN:(t='"true"')|(f='"false"');
//terminal ID:'~~~';
//terminal STRING:!('') (INT |WS | ID)* ;
//terminal mystr:
//(ANY_OTHER | STRING)*;

Template Part:
i exported this file from my eclipse to use it just import from eclipse Preferences>>LiquibaseEditor>>Templates


<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
- <templates>
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.kw_author=" deleted="false" description="" enabled="true" name="author">author="${user}"</template> 
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.kw_author=" deleted="false" description="" enabled="true" name="author">author="ozayd"</template> 
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.CHANGESET" deleted="false" description="" enabled="true" name="changeSet"><changeSet id="BLK-x-${date}-${time}" author="ozayd"> ${cursor} </changeSet></template> 
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.CREATEPROCEDURE" deleted="false" description="" enabled="true" name="CREATEPROCEDURE"><createProcedure> ${cursor} </createProcedure></template> 
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.CREATEPROCEDURE" deleted="false" description="" enabled="true" name="CREATEPROCEDURE"><createProcedure> ${cursor} </createProcedure></template> 
  <template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.Xlist" deleted="false" description="" enabled="true" name="databaseChangeLog"><?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd"> ${cursor} </databaseChangeLog></template> 
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.Xlist" deleted="false" description="" enabled="true" name="databaseChangeLog"><?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd"> ${cursor} </databaseChangeLog></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.INCLUDEFILE" deleted="false" description="" enabled="true" name="includeFile"><include file="${cursor}"/></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.INCLUDEFILE" deleted="false" description="" enabled="true" name="includeFile"><include file="${cursor}"/></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.ROOLBACK" deleted="false" description="" enabled="true" name="ROOLBACK"><roolback> ${cursor} </roolback></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.ROOLBACK" deleted="false" description="" enabled="true" name="ROOLBACK"><roolback> ${cursor} </roolback></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.Xlist" deleted="false" description="" enabled="true" name="sql"><sql> ${cursor} </sql></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.Xlist" deleted="false" description="" enabled="true" name="sql"><sql> ${cursor} </sql></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.SQL" deleted="false" description="" enabled="true" name="SQL"><sql> ${cursor} </sql></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.SQL" deleted="false" description="" enabled="true" name="SQL"><sql> ${cursor} </sql></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.SQLCHECK" deleted="false" description="" enabled="true" name="sqlCheck"><sqlCheck expectedResult="${cursor}expectedResult">"sqlStatement"</sqlCheck></template>
<template autoinsert="true" context="org.xtext.example.mydsl.LiquibaseEditor.SQLCHECK" deleted="false" description="" enabled="true" name="sqlCheck"><sqlCheck expectedResult="${cursor}expectedResult">"sqlStatement"</sqlCheck></template>
</templates>



No comments: