_prepare (statement, callback) {
    debug('ps(%d): prepare', IDS.get(this))

    if (typeof statement === 'function') {
      callback = statement
      statement = undefined
    }

    if (this.prepared) {
      return setImmediate(callback, new PreparedStatementError('Statement is already prepared.', 'EALREADYPREPARED'))
    }

    this.statement = statement || this.statement

    this.parent.acquire(this, (err, connection, config) => {
      if (err) return callback(err)

      this._acquiredConnection = connection
      this._acquiredConfig = config

      const req = new shared.driver.Request(this)
      req.stream = false
      req.output('handle', TYPES.Int)
      req.input('params', TYPES.NVarChar, ((() => {
        const result = []
        for (const name in this.parameters) {
          if (!objectHasProperty(this.parameters, name)) {
            continue
          }
          const param = this.parameters[name]
          result.push(`@${name} ${declare(param.type, param)}${param.io === 2 ? ' output' : ''}`)
        }
        return result
      })()).join(','))
      req.input('stmt', TYPES.NVarChar, this.statement)
      req.execute('sp_prepare', (err, result) => {
        if (err) {
          this.parent.release(this._acquiredConnection)
          this._acquiredConnection = null
          this._acquiredConfig = null

          return callback(err)
        }

        debug('ps(%d): prepared', IDS.get(this))

        this._handle = result.output.handle
        this.prepared = true

        callback(null)
      })
    })
  }
@private
@param {String} statement
@param {basicCallback} callback