protected static string Preprocess(string origScript, ISQLDatabase database, IDictionary <string, string> customPlaceholders = null)
        {
            // Replace simple types
            StringBuilder result = new StringBuilder(origScript);

            result = result.Replace("%TIMESTAMP%", GetType(typeof(DateTime), database)).
                     Replace("%CHAR%", GetType(typeof(Char), database)).
                     Replace("%BOOLEAN%", GetType(typeof(Boolean), database)).
                     Replace("%SINGLE%", GetType(typeof(Single), database)).
                     Replace("%DOUBLE%", GetType(typeof(Double), database)).
                     Replace("%SMALLINT%", GetType(typeof(Int16), database)).
                     Replace("%INTEGER%", GetType(typeof(Int32), database)).
                     Replace("%BIGINT%", GetType(typeof(Int64), database)).
                     Replace("%GUID%", GetType(typeof(Guid), database)).
                     Replace("%BINARY%", GetType(typeof(byte[]), database));

            // For extended replacements: First collect all patterns to be replaced...
            IDictionary <string, string> replacements = new Dictionary <string, string>();

            if (customPlaceholders != null)
            {
                foreach (var placeholder in customPlaceholders)
                {
                    replacements.Add(placeholder.Key, placeholder.Value);
                }
            }

            string interimStr = result.ToString();

            // %STRING([N])%
            Match match = new Regex(@"%STRING\((\d*)\)%").Match(interimStr);

            while (match.Success)
            {
                string pattern = match.Value;
                if (!replacements.ContainsKey(pattern))
                {
                    uint length = uint.Parse(match.Groups[1].Value);
                    replacements.Add(pattern, database.GetSQLVarLengthStringType(length));
                }
                match = match.NextMatch();
            }

            // %STRING_FIXED([N])%
            match = new Regex(@"%STRING_FIXED\((\d*)\)%").Match(interimStr);
            while (match.Success)
            {
                string pattern = match.Value;
                if (!replacements.ContainsKey(pattern))
                {
                    uint length = uint.Parse(match.Groups[1].Value);
                    replacements.Add(pattern, database.GetSQLFixedLengthStringType(length));
                }
                match = match.NextMatch();
            }

            // %CREATE_NEW_GUID% / %GET_LAST_GUID%
            string lastGuid = null;

            match = new Regex(@"(%CREATE_NEW_GUID%)|(%GET_LAST_GUID%)").Match(interimStr);
            while (match.Success)
            {
                Group g;
                if ((g = match.Groups[1]).Success) // %CREATE_NEW_GUID% matched
                {
                    result.Replace("%CREATE_NEW_GUID%", lastGuid = Guid.NewGuid().ToString("B"), g.Index, g.Length);
                }
                else if ((g = match.Groups[2]).Success) // %GET_LAST_GUID% matched
                {
                    result.Replace("%GET_LAST_GUID%", lastGuid, g.Index, g.Length);
                }
                match = match.NextMatch();
            }

            // ... then do the actual replacements
            result = replacements.Aggregate(result, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
            return(result.ToString());
        }
    protected static string Preprocess(string origScript, ISQLDatabase database)
    {
      // Replace simple types
      StringBuilder result = new StringBuilder(origScript);
      result = result.Replace("%TIMESTAMP%", GetType(typeof(DateTime), database)).
          Replace("%CHAR%", GetType(typeof(Char), database)).
          Replace("%BOOLEAN%", GetType(typeof(Boolean), database)).
          Replace("%SINGLE%", GetType(typeof(Single), database)).
          Replace("%DOUBLE%", GetType(typeof(Double), database)).
          Replace("%SMALLINT%", GetType(typeof(Int16), database)).
          Replace("%INTEGER%", GetType(typeof(Int32), database)).
          Replace("%BIGINT%", GetType(typeof(Int64), database)).
          Replace("%GUID%", GetType(typeof(Guid), database)).
          Replace("%BINARY%", GetType(typeof(byte[]), database));

      // For extended replacements: First collect all patterns to be replaced...
      IDictionary<string, string> replacements = new Dictionary<string, string>();

      string interimStr = result.ToString();

      // %STRING([N])%
      Match match = new Regex(@"%STRING\((\d*)\)%").Match(interimStr);
      while (match.Success)
      {
        string pattern = match.Value;
        if (!replacements.ContainsKey(pattern))
        {
          uint length = uint.Parse(match.Groups[1].Value);
          replacements.Add(pattern, database.GetSQLVarLengthStringType(length));
        }
        match = match.NextMatch();
      }

      // %STRING_FIXED([N])%
      match = new Regex(@"%STRING_FIXED\((\d*)\)%").Match(interimStr);
      while (match.Success)
      {
        string pattern = match.Value;
        if (!replacements.ContainsKey(pattern))
        {
          uint length = uint.Parse(match.Groups[1].Value);
          replacements.Add(pattern, database.GetSQLFixedLengthStringType(length));
        }
        match = match.NextMatch();
      }

      // %CREATE_NEW_GUID% / %GET_LAST_GUID%
      string lastGuid = null;
      match = new Regex(@"(%CREATE_NEW_GUID%)|(%GET_LAST_GUID%)").Match(interimStr);
      while (match.Success)
      {
        Group g;
        if ((g = match.Groups[1]).Success) // %CREATE_NEW_GUID% matched
          result.Replace("%CREATE_NEW_GUID%", lastGuid = Guid.NewGuid().ToString("B"), g.Index, g.Length);
        else if ((g = match.Groups[2]).Success) // %GET_LAST_GUID% matched
          result.Replace("%GET_LAST_GUID%", lastGuid, g.Index, g.Length);
        match = match.NextMatch();
      }

      // ... then do the actual replacements
      result = replacements.Aggregate(result, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
      return result.ToString();
    }