Wrestling with NAnt, MySQL and Input Scripts

written by Scott Muc on Sunday, December 28 2008

I'm writing an automated database build for a project I'm working on and wanted to avoid having to write batch scripts with paths that are tightly coupled to the build environment. I managed to write out the NAnt targets exactly the way that I wanted:

<?xml version="1.0"?>
<project name="Project">
  <property name="sql.dir" value="${base.dir}/sql"   />
  <property name="initialize.ddl" value="${sql.dir}/initial.ddl.sql"   />

  <target name="db.init">
    <call target="db.create"  />
  </target>

  <target name="db.create" description="Creates the Database and tables">
    <exec        
        basedir="${mysql.dir}"
              program="mysql.exe"
              workingdir="${build.artifacts.dir}">
      <arg value="--user=${mysql.user}"  />
      <arg value="--password=${mysql.password}"  />
      <arg line="&lt; ${initialize.ddl}"  /> 
    </exec>
  </target>
</project>

Unfortunately when I run the db.create task it fails. I don't get any clear errors messages, only output from mysql.exe that explains how it should be called. I tried the syntax manually from the command line and it worked no problem. The line where I have the XML encoded less than sign seems to be the culprit but I can't figure out how the syntax should be.

I ended up working on it much longer than I wanted to and still never figured it out. I ended up re-doing it using a template batch script. The batch script contains some placeholders that NAnt will replace using a filter chain. This means that with some tweaks to the local properties and the NAnt task and batch script will work on any box. I think it's ugly, but it works.

Here's the NAnt Xml:

<?xml version="1.0"?>
<project name="Project">
  <property name="sql.dir" value="${base.dir}/sql"  />
  <property name="sql.exec" value="${sql.dir}/sql-exec.bat"  />

  <target name="db.init">
    <call target="db.create"  />
  </target>

  <target name="expand.sql-exec.template">
    <copy     file="${sql.exec}.template"
            tofile="${sql.exec}"
            overwrite="true">
      <filterchain>
        <replacetokens>
          <token key="mysql.dir" value="${mysql.dir}"   />
          <token key="mysql.user" value="${mysql.user}"  />
          <token key="mysql.password" value="${mysql.password}"   />
          <token key="sql.script" value="${sql.script}"  />
        </replacetokens>
      </filterchain>
    </copy>    
  </target>

  <target name="execute.sql.script">
    <exec
        basedir="${sql.dir}"
              program="${sql.exec}"
              workingdir="${sql.dir}">
    </exec>        
  </target>

  <target name="db.create" description="Creates the Database and tables">
    <property name="sql.script" value="initial.ddl.sql"  />
    <call target="expand.sql-exec.template"  />
    <call target="execute.sql.script"  />  
  </target>
</project>

 And the sql-exec.bat.template looks like:

"@mysql.dir@\mysql.exe" --user=@mysql.user@ --password=@mysql.password@ < @sql.script@

 The variables that I'm using in both NAnt scripts are inside a file called local.properties.xml which are always machine specific and not in the version controlled files. If anyone can drop me a hint on how to get the first syntax style working please let me know.

Similar Posts

  1. Unit Testing Domain Persistence With NDbUnit, NHibernate and SQLite
  2. My Developer Resolutions For 2009
  3. My Developer Resolutions For 2010

Comments

  • Bigrockfan on on 12.29.2008 at 6:50 PM

    Bigrockfan avatar

    I am on the seat of my pants wondering if you are going to figure this problem out. I got this twitter message halfway thought the new Bond film and had to leave the theatre because I started fretting about your NAnt script issue. I even asked the guy sitting next to me but he just told me to shut up and stole some of my popcorn.

    Can you hurry up and post again before New Year's eve? I would hate to cancel my plans because of distraction.

Post a comment

Options:

Size

Colors