// Generated by CoffeeScript 1.7.1
var EPOCH_DATE, MAX, NULL, TYPE, UTC_EPOCH_DATE, YEAR_ONE, alias, guidParser, id, type, typeByName, _i, _len, _ref;

guidParser = require('./guid-parser');

NULL = (1 << 16) - 1;

EPOCH_DATE = new Date(1900, 0, 1);

UTC_EPOCH_DATE = new Date(Date.UTC(1900, 0, 1));

YEAR_ONE = Date.UTC(2000, 0, -730118);

MAX = (1 << 16) - 1;

TYPE = {
  0x1F: {
    type: 'NULL',
    name: 'Null'
  },
  0x30: {
    type: 'INT1',
    name: 'TinyInt',
    declaration: function(parameter) {
      return 'tinyint';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.IntN.id);
      return buffer.writeUInt8(1);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(1);
        return buffer.writeUInt8(parseInt(parameter.value));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x32: {
    type: 'BIT',
    name: 'Bit',
    declaration: function(parameter) {
      return 'bit';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.BitN.id);
      return buffer.writeUInt8(1);
    },
    writeParameterData: function(buffer, parameter) {
      if (typeof parameter.value === 'undefined' || parameter.value === null) {
        return buffer.writeUInt8(0);
      } else {
        buffer.writeUInt8(1);
        return buffer.writeUInt8(parameter.value ? 1 : 0);
      }
    }
  },
  0x34: {
    type: 'INT2',
    name: 'SmallInt',
    declaration: function(parameter) {
      return 'smallint';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.IntN.id);
      return buffer.writeUInt8(2);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(2);
        return buffer.writeInt16LE(parseInt(parameter.value));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x38: {
    type: 'INT4',
    name: 'Int',
    declaration: function(parameter) {
      return 'int';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.IntN.id);
      return buffer.writeUInt8(4);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(4);
        return buffer.writeInt32LE(parseInt(parameter.value));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3A: {
    type: 'DATETIM4',
    name: 'SmallDateTime',
    declaration: function(parameter) {
      return 'smalldatetime';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.DateTimeN.id);
      return buffer.writeUInt8(4);
    },
    writeParameterData: function(buffer, parameter, options) {
      var days, minutes;
      if (parameter.value != null) {
        if (options.useUTC) {
          days = Math.floor((parameter.value.getTime() - UTC_EPOCH_DATE.getTime()) / (1000 * 60 * 60 * 24));
          minutes = (parameter.value.getUTCHours() * 60) + parameter.value.getUTCMinutes();
        } else {
          days = Math.floor((parameter.value.getTime() - EPOCH_DATE.getTime()) / (1000 * 60 * 60 * 24));
          minutes = (parameter.value.getHours() * 60) + parameter.value.getMinutes();
        }
        buffer.writeUInt8(4);
        buffer.writeUInt16LE(days);
        return buffer.writeUInt16LE(minutes);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3B: {
    type: 'FLT4',
    name: 'Real',
    declaration: function(parameter) {
      return 'real';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.FloatN.id);
      return buffer.writeUInt8(4);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(4);
        return buffer.writeFloatLE(parseFloat(parameter.value));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3C: {
    type: 'MONEY',
    name: 'Money',
    declaration: function(parameter) {
      return "money";
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.MoneyN.id);
      return buffer.writeUInt8(8);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(8);
        return buffer.writeMoney(parameter.value * 10000);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3D: {
    type: 'DATETIME',
    name: 'DateTime',
    declaration: function(parameter) {
      return 'datetime';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.DateTimeN.id);
      return buffer.writeUInt8(8);
    },
    writeParameterData: function(buffer, parameter, options) {
      var days, milliseconds, seconds, threeHundredthsOfSecond;
      if (parameter.value != null) {
        if (options.useUTC) {
          days = Math.floor((parameter.value.getTime() - UTC_EPOCH_DATE.getTime()) / (1000 * 60 * 60 * 24));
          seconds = parameter.value.getUTCHours() * 60 * 60;
          seconds += parameter.value.getUTCMinutes() * 60;
          seconds += parameter.value.getUTCSeconds();
          milliseconds = (seconds * 1000) + parameter.value.getUTCMilliseconds();
        } else {
          days = Math.floor((parameter.value.getTime() - EPOCH_DATE.getTime()) / (1000 * 60 * 60 * 24));
          seconds = parameter.value.getHours() * 60 * 60;
          seconds += parameter.value.getMinutes() * 60;
          seconds += parameter.value.getSeconds();
          milliseconds = (seconds * 1000) + parameter.value.getMilliseconds();
        }
        threeHundredthsOfSecond = milliseconds / (3 + (1 / 3));
        threeHundredthsOfSecond = Math.floor(threeHundredthsOfSecond);
        buffer.writeUInt8(8);
        buffer.writeInt32LE(days);
        return buffer.writeUInt32LE(threeHundredthsOfSecond);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3E: {
    type: 'FLT8',
    name: 'Float',
    declaration: function(parameter) {
      return 'float';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.FloatN.id);
      return buffer.writeUInt8(8);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(8);
        return buffer.writeDoubleLE(parseFloat(parameter.value));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x37: {
    type: 'DECIMAL',
    name: 'Decimal',
    hasPrecision: true,
    hasScale: true,
    declaration: function(parameter) {
      return "decimal(" + (this.resolvePrecision(parameter)) + ", " + (this.resolveScale(parameter)) + ")";
    },
    resolvePrecision: function(parameter) {
      if (parameter.precision != null) {
        return parameter.precision;
      } else if (parameter.value === null) {
        return 1;
      } else {
        return 18;
      }
    },
    resolveScale: function(parameter) {
      if (parameter.scale != null) {
        return parameter.scale;
      } else {
        return 0;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.DecimalN.id);
      if (parameter.precision <= 9) {
        buffer.writeUInt8(5);
      } else if (parameter.precision <= 19) {
        buffer.writeUInt8(9);
      } else if (parameter.precision <= 28) {
        buffer.writeUInt8(13);
      } else {
        buffer.writeUInt8(17);
      }
      buffer.writeUInt8(parameter.precision);
      return buffer.writeUInt8(parameter.scale);
    },
    writeParameterData: function(buffer, parameter) {
      var sign, value;
      if (parameter.value != null) {
        sign = parameter.value < 0 ? 0 : 1;
        value = Math.round(Math.abs(parameter.value * Math.pow(10, parameter.scale)));
        if (parameter.precision <= 9) {
          buffer.writeUInt8(5);
          buffer.writeUInt8(sign);
          return buffer.writeUInt32LE(value);
        } else if (parameter.precision <= 19) {
          buffer.writeUInt8(9);
          buffer.writeUInt8(sign);
          return buffer.writeUInt64LE(value);
        } else if (parameter.precision <= 28) {
          buffer.writeUInt8(13);
          buffer.writeUInt8(sign);
          buffer.writeUInt64LE(value);
          return buffer.writeUInt32LE(0x00000000);
        } else {
          buffer.writeUInt8(17);
          buffer.writeUInt8(sign);
          buffer.writeUInt64LE(value);
          buffer.writeUInt32LE(0x00000000);
          return buffer.writeUInt32LE(0x00000000);
        }
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x3F: {
    type: 'NUMERIC',
    name: 'Numeric',
    hasPrecision: true,
    hasScale: true,
    declaration: function(parameter) {
      return "numeric(" + (this.resolvePrecision(parameter)) + ", " + (this.resolveScale(parameter)) + ")";
    },
    resolvePrecision: function(parameter) {
      if (parameter.precision != null) {
        return parameter.precision;
      } else if (parameter.value === null) {
        return 1;
      } else {
        return 18;
      }
    },
    resolveScale: function(parameter) {
      if (parameter.scale != null) {
        return parameter.scale;
      } else {
        return 0;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.NumericN.id);
      if (parameter.precision <= 9) {
        buffer.writeUInt8(5);
      } else if (parameter.precision <= 19) {
        buffer.writeUInt8(9);
      } else if (parameter.precision <= 28) {
        buffer.writeUInt8(13);
      } else {
        buffer.writeUInt8(17);
      }
      buffer.writeUInt8(parameter.precision);
      return buffer.writeUInt8(parameter.scale);
    },
    writeParameterData: function(buffer, parameter) {
      var sign, value;
      if (parameter.value != null) {
        sign = parameter.value < 0 ? 0 : 1;
        value = Math.round(Math.abs(parameter.value * Math.pow(10, parameter.scale)));
        if (parameter.precision <= 9) {
          buffer.writeUInt8(5);
          buffer.writeUInt8(sign);
          return buffer.writeUInt32LE(value);
        } else if (parameter.precision <= 19) {
          buffer.writeUInt8(9);
          buffer.writeUInt8(sign);
          return buffer.writeUInt64LE(value);
        } else if (parameter.precision <= 28) {
          buffer.writeUInt8(13);
          buffer.writeUInt8(sign);
          buffer.writeUInt64LE(value);
          return buffer.writeUInt32LE(0x00000000);
        } else {
          buffer.writeUInt8(17);
          buffer.writeUInt8(sign);
          buffer.writeUInt64LE(value);
          buffer.writeUInt32LE(0x00000000);
          return buffer.writeUInt32LE(0x00000000);
        }
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x7A: {
    type: 'MONEY4',
    name: 'SmallMoney',
    declaration: function(parameter) {
      return "smallmoney";
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.MoneyN.id);
      return buffer.writeUInt8(4);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(4);
        return buffer.writeInt32LE(parameter.value * 10000);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x7F: {
    type: 'INT8',
    name: 'BigInt',
    declaration: function(parameter) {
      return 'bigint';
    },
    writeTypeInfo: function(buffer) {
      buffer.writeUInt8(typeByName.IntN.id);
      return buffer.writeUInt8(8);
    },
    writeParameterData: function(buffer, parameter) {
      var val;
      if (parameter.value != null) {
        val = typeof parameter.value !== 'number' ? parameter.value : parseInt(parameter.value);
        buffer.writeUInt8(8);
        return buffer.writeInt64LE(val);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x22: {
    type: 'IMAGE',
    name: 'Image',
    hasTableName: true,
    hasTextPointerAndTimestamp: true,
    dataLengthLength: 4,
    declaration: function(parameter) {
      return 'image';
    },
    resolveLength: function(parameter) {
      if (parameter.value != null) {
        return parameter.value.length;
      } else {
        return -1;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      return buffer.writeInt32LE(parameter.length);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeInt32LE(parameter.length);
        return buffer.writeBuffer(parameter.value);
      } else {
        return buffer.writeInt32LE(parameter.length);
      }
    }
  },
  0x23: {
    type: 'TEXT',
    name: 'Text',
    hasCollation: true,
    hasTableName: true,
    hasTextPointerAndTimestamp: true,
    dataLengthLength: 4,
    declaration: function(parameter) {
      return 'text';
    },
    resolveLength: function(parameter) {
      if (parameter.value != null) {
        return parameter.value.length;
      } else {
        return -1;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.Text.id);
      return buffer.writeInt32LE(parameter.length);
    },
    writeParameterData: function(buffer, parameter) {
      buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00]));
      if (parameter.value != null) {
        buffer.writeInt32LE(parameter.length);
        return buffer.writeString(parameter.value.toString(), 'ascii');
      } else {
        return buffer.writeInt32LE(parameter.length);
      }
    }
  },
  0x24: {
    type: 'GUIDN',
    name: 'UniqueIdentifierN',
    aliases: ['UniqueIdentifier'],
    dataLengthLength: 1,
    declaration: function(parameter) {
      return 'uniqueidentifier';
    },
    resolveLength: function(parameter) {
      return 16;
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(typeByName.UniqueIdentifierN.id);
      return buffer.writeUInt8(0x10);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(0x10);
        return buffer.writeBuffer(new Buffer(guidParser.guidToArray(parameter.value)));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x26: {
    type: 'INTN',
    name: 'IntN',
    dataLengthLength: 1
  },
  0x63: {
    type: 'NTEXT',
    name: 'NText',
    hasCollation: true,
    hasTableName: true,
    hasTextPointerAndTimestamp: true,
    dataLengthLength: 4
  },
  0x68: {
    type: 'BITN',
    name: 'BitN',
    dataLengthLength: 1
  },
  0x6A: {
    type: 'DECIMALN',
    name: 'DecimalN',
    dataLengthLength: 1,
    hasPrecision: true,
    hasScale: true
  },
  0x6C: {
    type: 'NUMERICN',
    name: 'NumericN',
    dataLengthLength: 1,
    hasPrecision: true,
    hasScale: true
  },
  0x6D: {
    type: 'FLTN',
    name: 'FloatN',
    dataLengthLength: 1
  },
  0x6E: {
    type: 'MONEYN',
    name: 'MoneyN',
    dataLengthLength: 1
  },
  0x6F: {
    type: 'DATETIMN',
    name: 'DateTimeN',
    dataLengthLength: 1
  },
  0xA5: {
    type: 'BIGVARBIN',
    name: 'VarBinary',
    dataLengthLength: 2,
    maximumLength: 8000,
    declaration: function(parameter) {
      var length;
      if (parameter.length) {
        length = parameter.length;
      } else if (parameter.value != null) {
        length = parameter.value.length || 1;
      } else if (parameter.value === null && !parameter.output) {
        length = 1;
      } else {
        length = this.maximumLength;
      }
      if (length <= this.maximumLength) {
        return "varbinary(" + length + ")";
      } else {
        return "varbinary(max)";
      }
    },
    resolveLength: function(parameter) {
      if (parameter.length != null) {
        return parameter.length;
      } else if (parameter.value != null) {
        return parameter.value.length;
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      if (parameter.length <= this.maximumLength) {
        return buffer.writeUInt16LE(this.maximumLength);
      } else {
        return buffer.writeUInt16LE(MAX);
      }
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUsVarbyte(parameter.value);
        } else {
          return buffer.writePLPBody(parameter.value);
        }
      } else {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUInt16LE(NULL);
        } else {
          buffer.writeUInt32LE(0xFFFFFFFF);
          return buffer.writeUInt32LE(0xFFFFFFFF);
        }
      }
    }
  },
  0xA7: {
    type: 'BIGVARCHR',
    name: 'VarChar',
    hasCollation: true,
    dataLengthLength: 2,
    maximumLength: 8000,
    declaration: function(parameter) {
      var length;
      if (parameter.length) {
        length = parameter.length;
      } else if (parameter.value != null) {
        length = parameter.value.toString().length || 1;
      } else if (parameter.value === null && !parameter.output) {
        length = 1;
      } else {
        length = this.maximumLength;
      }
      if (length <= this.maximumLength) {
        return "varchar(" + length + ")";
      } else {
        return "varchar(max)";
      }
    },
    resolveLength: function(parameter) {
      if (parameter.length != null) {
        return parameter.length;
      } else if (parameter.value != null) {
        if (Buffer.isBuffer(parameter.value)) {
          return parameter.value.length || 1;
        } else {
          return parameter.value.toString().length || 1;
        }
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      if (parameter.length <= this.maximumLength) {
        buffer.writeUInt16LE(this.maximumLength);
      } else {
        buffer.writeUInt16LE(MAX);
      }
      return buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00]));
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUsVarbyte(parameter.value, 'ascii');
        } else {
          return buffer.writePLPBody(parameter.value, 'ascii');
        }
      } else {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUInt16LE(NULL);
        } else {
          buffer.writeUInt32LE(0xFFFFFFFF);
          return buffer.writeUInt32LE(0xFFFFFFFF);
        }
      }
    }
  },
  0xAD: {
    type: 'BIGBinary',
    name: 'Binary',
    dataLengthLength: 2,
    maximumLength: 8000,
    declaration: function(parameter) {
      return 'binary';
    },
    resolveLength: function(parameter) {
      if (parameter.value != null) {
        return parameter.value.length;
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      return buffer.writeUInt16LE(parameter.length);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt16LE(parameter.length);
        return buffer.writeBuffer(parameter.value.slice(0, Math.min(parameter.length, this.maximumLength)));
      } else {
        return buffer.writeUInt16LE(NULL);
      }
    }
  },
  0xAF: {
    type: 'BIGCHAR',
    name: 'Char',
    hasCollation: true,
    dataLengthLength: 2,
    maximumLength: 8000,
    declaration: function(parameter) {
      var length;
      if (parameter.length) {
        length = parameter.length;
      } else if (parameter.value != null) {
        length = parameter.value.toString().length || 1;
      } else if (parameter.value === null && !parameter.output) {
        length = 1;
      } else {
        length = this.maximumLength;
      }
      if (length < this.maximumLength) {
        return "char(" + length + ")";
      } else {
        return "char(" + this.maximumLength + ")";
      }
    },
    resolveLength: function(parameter) {
      if (parameter.length != null) {
        return parameter.length;
      } else if (parameter.value != null) {
        if (Buffer.isBuffer(parameter.value)) {
          return parameter.value.length || 1;
        } else {
          return parameter.value.toString().length || 1;
        }
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      buffer.writeUInt16LE(parameter.length);
      return buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00]));
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        return buffer.writeUsVarbyte(parameter.value, 'ascii');
      } else {
        return buffer.writeUInt16LE(NULL);
      }
    }
  },
  0xE7: {
    type: 'NVARCHAR',
    name: 'NVarChar',
    hasCollation: true,
    dataLengthLength: 2,
    maximumLength: 4000,
    declaration: function(parameter) {
      var length;
      if (parameter.length) {
        length = parameter.length;
      } else if (parameter.value != null) {
        length = parameter.value.toString().length || 1;
      } else if (parameter.value === null && !parameter.output) {
        length = 1;
      } else {
        length = this.maximumLength;
      }
      if (length <= this.maximumLength) {
        return "nvarchar(" + length + ")";
      } else {
        return "nvarchar(max)";
      }
    },
    resolveLength: function(parameter) {
      if (parameter.length != null) {
        return parameter.length;
      } else if (parameter.value != null) {
        if (Buffer.isBuffer(parameter.value)) {
          return (parameter.value.length / 2) || 1;
        } else {
          return parameter.value.toString().length || 1;
        }
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      if (parameter.length <= this.maximumLength) {
        buffer.writeUInt16LE(parameter.length * 2);
      } else {
        buffer.writeUInt16LE(MAX);
      }
      return buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00]));
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUsVarbyte(parameter.value, 'ucs2');
        } else {
          return buffer.writePLPBody(parameter.value, 'ucs2');
        }
      } else {
        if (parameter.length <= this.maximumLength) {
          return buffer.writeUInt16LE(NULL);
        } else {
          buffer.writeUInt32LE(0xFFFFFFFF);
          return buffer.writeUInt32LE(0xFFFFFFFF);
        }
      }
    }
  },
  0xEF: {
    type: 'NCHAR',
    name: 'NChar',
    hasCollation: true,
    dataLengthLength: 2,
    maximumLength: 4000,
    declaration: function(parameter) {
      var length;
      if (parameter.length) {
        length = parameter.length;
      } else if (parameter.value != null) {
        length = parameter.value.toString().length || 1;
      } else if (parameter.value === null && !parameter.output) {
        length = 1;
      } else {
        length = this.maximumLength;
      }
      if (length < this.maximumLength) {
        return "nchar(" + length + ")";
      } else {
        return "nchar(" + this.maximumLength + ")";
      }
    },
    resolveLength: function(parameter) {
      if (parameter.length != null) {
        return parameter.length;
      } else if (parameter.value != null) {
        if (Buffer.isBuffer(parameter.value)) {
          return (parameter.value.length / 2) || 1;
        } else {
          return parameter.value.toString().length || 1;
        }
      } else {
        return this.maximumLength;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      buffer.writeUInt16LE(parameter.length * 2);
      return buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x00]));
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        return buffer.writeUsVarbyte(parameter.value, 'ucs2');
      } else {
        return buffer.writeUInt16LE(NULL);
      }
    }
  },
  0xF1: {
    type: 'XML',
    name: 'Xml',
    hasSchemaPresent: true
  },
  0x29: {
    type: 'TIMEN',
    name: 'TimeN',
    aliases: ['Time'],
    hasScale: true,
    dataLengthLength: 0,
    dataLengthFromScale: function(scale) {
      switch (scale) {
        case 0:
        case 1:
        case 2:
          return 3;
        case 3:
        case 4:
          return 4;
        case 5:
        case 6:
        case 7:
          return 5;
      }
    },
    declaration: function(parameter) {
      return "time(" + (this.resolveScale(parameter)) + ")";
    },
    resolveScale: function(parameter) {
      if (parameter.scale != null) {
        return parameter.scale;
      } else if (parameter.value === null) {
        return 0;
      } else {
        return 7;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      return buffer.writeUInt8(parameter.scale);
    },
    writeParameterData: function(buffer, parameter) {
      var time, _ref;
      if (parameter.value != null) {
        parameter.value.setUTCFullYear(1970);
        parameter.value.setUTCMonth(0);
        parameter.value.setUTCDate(1);
        time = (+parameter.value / 1000 + ((_ref = parameter.value.nanosecondDelta) != null ? _ref : 0)) * Math.pow(10, parameter.scale);
        switch (parameter.scale) {
          case 0:
          case 1:
          case 2:
            buffer.writeUInt8(3);
            return buffer.writeUInt24LE(time);
          case 3:
          case 4:
            buffer.writeUInt8(4);
            return buffer.writeUInt32LE(time);
          case 5:
          case 6:
          case 7:
            buffer.writeUInt8(5);
            return buffer.writeUInt40LE(time);
        }
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x28: {
    type: 'DATEN',
    name: 'DateN',
    aliases: ['Date'],
    dataLengthLength: 0,
    declaration: function(parameter) {
      return "date";
    },
    writeTypeInfo: function(buffer, parameter) {
      return buffer.writeUInt8(this.id);
    },
    writeParameterData: function(buffer, parameter) {
      if (parameter.value != null) {
        buffer.writeUInt8(3);
        return buffer.writeUInt24LE(Math.floor((+parameter.value - YEAR_ONE) / 86400000));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x2A: {
    type: 'DATETIME2N',
    name: 'DateTime2N',
    aliases: ['DateTime2'],
    hasScale: true,
    dataLengthLength: 0,
    dataLengthFromScale: function(scale) {
      switch (scale) {
        case 0:
        case 1:
        case 2:
          return 3;
        case 3:
        case 4:
          return 4;
        case 5:
        case 6:
        case 7:
          return 5;
      }
    },
    declaration: function(parameter) {
      return "datetime2(" + (this.resolveScale(parameter)) + ")";
    },
    resolveScale: function(parameter) {
      if (parameter.scale != null) {
        return parameter.scale;
      } else if (parameter.value === null) {
        return 0;
      } else {
        return 7;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      return buffer.writeUInt8(parameter.scale);
    },
    writeParameterData: function(buffer, parameter) {
      var time, _ref;
      if (parameter.value != null) {
        time = new Date(+parameter.value);
        time.setUTCFullYear(1970);
        time.setUTCMonth(0);
        time.setUTCDate(1);
        time = (+time / 1000 + ((_ref = parameter.value.nanosecondDelta) != null ? _ref : 0)) * Math.pow(10, parameter.scale);
        switch (parameter.scale) {
          case 0:
          case 1:
          case 2:
            buffer.writeUInt8(6);
            buffer.writeUInt24LE(time);
            break;
          case 3:
          case 4:
            buffer.writeUInt8(7);
            buffer.writeUInt32LE(time);
            break;
          case 5:
          case 6:
          case 7:
            buffer.writeUInt8(8);
            buffer.writeUInt40LE(time);
        }
        return buffer.writeUInt24LE(Math.floor((+parameter.value - YEAR_ONE) / 86400000));
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0x2B: {
    type: 'DATETIMEOFFSETN',
    name: 'DateTimeOffsetN',
    aliases: ['DateTimeOffset'],
    hasScale: true,
    dataLengthLength: 0,
    dataLengthFromScale: function(scale) {
      switch (scale) {
        case 0:
        case 1:
        case 2:
          return 3;
        case 3:
        case 4:
          return 4;
        case 5:
        case 6:
        case 7:
          return 5;
      }
    },
    declaration: function(parameter) {
      return "datetimeoffset(" + (this.resolveScale(parameter)) + ")";
    },
    resolveScale: function(parameter) {
      if (parameter.scale != null) {
        return parameter.scale;
      } else if (parameter.value === null) {
        return 0;
      } else {
        return 7;
      }
    },
    writeTypeInfo: function(buffer, parameter) {
      buffer.writeUInt8(this.id);
      return buffer.writeUInt8(parameter.scale);
    },
    writeParameterData: function(buffer, parameter) {
      var offset, time, _ref;
      if (parameter.value != null) {
        time = new Date(+parameter.value);
        time.setUTCFullYear(1970);
        time.setUTCMonth(0);
        time.setUTCDate(1);
        time = (+time / 1000 + ((_ref = parameter.value.nanosecondDelta) != null ? _ref : 0)) * Math.pow(10, parameter.scale);
        offset = -parameter.value.getTimezoneOffset();
        switch (parameter.scale) {
          case 0:
          case 1:
          case 2:
            buffer.writeUInt8(8);
            buffer.writeUInt24LE(time);
            break;
          case 3:
          case 4:
            buffer.writeUInt8(9);
            buffer.writeUInt32LE(time);
            break;
          case 5:
          case 6:
          case 7:
            buffer.writeUInt8(10);
            buffer.writeUInt40LE(time);
        }
        buffer.writeUInt24LE(Math.floor((+parameter.value - YEAR_ONE) / 86400000));
        return buffer.writeInt16LE(offset);
      } else {
        return buffer.writeUInt8(0);
      }
    }
  },
  0xF0: {
    type: 'UDTTYPE',
    name: 'UDT',
    hasUDTInfo: true
  },
  0xF3: {
    type: 'TVPTYPE',
    name: 'TVP',
    declaration: function(parameter) {
      return "" + parameter.value.name + " readonly";
    },
    writeTypeInfo: function(buffer, parameter) {
      var _ref, _ref1, _ref2, _ref3;
      buffer.writeUInt8(this.id);
      buffer.writeBVarchar("");
      buffer.writeBVarchar((_ref = (_ref1 = parameter.value) != null ? _ref1.schema : void 0) != null ? _ref : "");
      return buffer.writeBVarchar((_ref2 = (_ref3 = parameter.value) != null ? _ref3.name : void 0) != null ? _ref2 : "");
    },
    writeParameterData: function(buffer, parameter, options) {
      var column, index, param, row, value, _i, _j, _k, _len, _len1, _len2, _ref, _ref1;
      if (parameter.value == null) {
        buffer.writeUInt16LE(0xFFFF);
        buffer.writeUInt8(0x00);
        buffer.writeUInt8(0x00);
        return;
      }
      buffer.writeUInt16LE(parameter.value.columns.length);
      _ref = parameter.value.columns;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        column = _ref[_i];
        buffer.writeUInt32LE(0x00000000);
        buffer.writeUInt16LE(0x0000);
        column.type.writeTypeInfo(buffer, column);
        buffer.writeBVarchar("");
      }
      buffer.writeUInt8(0x00);
      _ref1 = parameter.value.rows;
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        row = _ref1[_j];
        buffer.writeUInt8(0x01);
        for (index = _k = 0, _len2 = row.length; _k < _len2; index = ++_k) {
          value = row[index];
          param = {
            value: value,
            length: parameter.value.columns[index].length,
            scale: parameter.value.columns[index].scale,
            precision: parameter.value.columns[index].precision
          };
          parameter.value.columns[index].type.writeParameterData(buffer, param, options);
        }
      }
      return buffer.writeUInt8(0x00);
    }
  }
};


/*
  CHARTYPE:             0x2F  # Char (legacy support)
  VARCHARTYPE:          0x27  # VarChar (legacy support)
  BINARYTYPE:           0x2D  # Binary (legacy support)
  VARBINARYTYPE:        0x25  # VarBinary (legacy support)

  SSVARIANTTYPE:        0x62  # Sql_Variant (introduced in TDS 7.2)
 */

typeByName = {};

for (id in TYPE) {
  type = TYPE[id];
  type.id = parseInt(id, 10);
  typeByName[type.name] = type;
  if ((type.aliases != null) && type.aliases instanceof Array) {
    _ref = type.aliases;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      alias = _ref[_i];
      if (!typeByName[alias]) {
        typeByName[alias] = type;
      }
    }
  }
}

exports.TYPE = TYPE;

exports.typeByName = typeByName;
