Code coverage report for upstream/lib/dialects/sqlite/query-interface.js

Statements: 3.77% (2 / 53)      Branches: 0% (0 / 10)      Functions: 0% (0 / 20)      Lines: 3.77% (2 / 53)     

All files » upstream/lib/dialects/sqlite/ » query-interface.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 1781               1                                                                                                                                                                                                                                                                                                                                                  
var Utils = require("../../utils")
 
/**
 Returns an object that treats SQLite's inabilities to do certain queries.
 
 @class QueryInterface
 @static
 */
var QueryInterface = module.exports = {
  /**
    A wrapper that fixes SQLite's inability to remove columns from existing tables.
    It will create a backup of the table, drop the table afterwards and create a
    new table with the same name but without the obsolete column.
 
    @method removeColumn
    @for    QueryInterface
 
    @param  {String} tableName     The name of the table.
    @param  {String} attributeName The name of the attribute that we want to remove.
    @param  {CustomEventEmitter} emitter       The EventEmitter from outside.
    @param  {Function} queryAndEmit  The function from outside that triggers some events to get triggered.
 
    @since 1.6.0
   */
  removeColumn: function(tableName, attributeName, emitter, queryAndEmit) {
    this.describeTable(tableName).complete(function(err, fields) {
      if (err) {
        emitter.emit('error', err)
      } else {
        delete fields[attributeName]
 
        var sql        = this.QueryGenerator.removeColumnQuery(tableName, fields)
          , subQueries = sql.split(';').filter(function(q) { return q !== '' })
 
        QueryInterface.execMultiQuery.call(this, subQueries, 'removeColumn', emitter, queryAndEmit)
      }
    }.bind(this))
  },
 
  /**
    A wrapper that fixes SQLite's inability to change columns from existing tables.
    It will create a backup of the table, drop the table afterwards and create a
    new table with the same name but with a modified version of the respective column.
 
    @method changeColumn
    @for    QueryInterface
 
    @param  {String} tableName The name of the table.
    @param  {Object} attributes An object with the attribute's name as key and it's options as value object.
    @param  {CustomEventEmitter} emitter The EventEmitter from outside.
    @param  {Function} queryAndEmit The function from outside that triggers some events to get triggered.
 
    @since 1.6.0
   */
  changeColumn: function(tableName, attributes, emitter, queryAndEmit) {
    var attributeName = Utils._.keys(attributes)[0]
 
    this.describeTable(tableName).complete(function(err, fields) {
      if (err) {
        emitter.emit('error', err)
      } else {
        fields[attributeName] = attributes[attributeName]
 
        var sql        = this.QueryGenerator.removeColumnQuery(tableName, fields)
          , subQueries = sql.split(';').filter(function(q) { return q !== '' })
 
        QueryInterface.execMultiQuery.call(this, subQueries, 'changeColumn', emitter, queryAndEmit)
      }
    }.bind(this))
  },
 
  /**
    A wrapper that fixes SQLite's inability to rename columns from existing tables.
    It will create a backup of the table, drop the table afterwards and create a
    new table with the same name but with a renamed version of the respective column.
 
    @method renameColumn
    @for    QueryInterface
 
    @param  {String} tableName The name of the table.
    @param  {String} attrNameBefore The name of the attribute before it was renamed.
    @param  {String} attrNameAfter The name of the attribute after it was renamed.
    @param  {CustomEventEmitter} emitter The EventEmitter from outside.
    @param  {Function} queryAndEmit The function from outside that triggers some events to get triggered.
 
    @since 1.6.0
   */
  renameColumn: function(tableName, attrNameBefore, attrNameAfter, emitter, queryAndEmit) {
    this.describeTable(tableName).complete(function(err, fields) {
      if (err) {
        emitter.emit('error', err)
      } else {
        fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore])
        delete fields[attrNameBefore]
 
        var sql        = this.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields)
          , subQueries = sql.split(';').filter(function(q) { return q !== '' })
 
        QueryInterface.execMultiQuery.call(this, subQueries, 'renameColumn', emitter, queryAndEmit)
      }
    }.bind(this))
  },
 
  execMultiQuery: function(queries, methodName, emitter, queryAndEmit) {
    var chainer = new Utils.QueryChainer()
 
    queries.splice(0, queries.length - 1).forEach(function(query) {
      chainer.add(this.sequelize, 'query', [query + ";", null, { raw: true }])
    }.bind(this))
 
    chainer
      .runSerially()
      .complete(function(err) {
        if (err) {
          emitter.emit(methodName, err)
          emitter.emit('error', err)
        } else {
          queryAndEmit.call(this, queries.splice(queries.length - 1)[0], methodName, {}, emitter)
        }
      }.bind(this))
  },
 
  dropAllTables: function() {
    var self = this
 
   return new Utils.CustomEventEmitter(function(dropAllTablesEmitter) {
      var events  = []
        , chainer = new Utils.QueryChainer()
        , onError = function(err) {
            self.emit('dropAllTables', err)
            dropAllTablesEmitter.emit('error', err)
          }
 
      self
        .showAllTables()
        .error(onError)
        .success(function(tableNames) {
          self
            .sequelize
            .query('PRAGMA foreign_keys;')
            .proxy(dropAllTablesEmitter, { events: ['sql'] })
            .error(onError)
            .success(function(result) {
              var foreignKeysAreEnabled = result.foreign_keys === 1
 
              if (foreignKeysAreEnabled) {
                var queries = []
 
                queries.push('PRAGMA foreign_keys = OFF')
 
                tableNames.forEach(function(tableName) {
                  queries.push(self.QueryGenerator.dropTableQuery(tableName).replace(';', ''))
                })
 
                queries.push('PRAGMA foreign_keys = ON')
 
                QueryInterface.execMultiQuery.call(self, queries, 'dropAllTables', dropAllTablesEmitter, self.queryAndEmit)
              } else {
                // add the table removal query to the chainer
                tableNames.forEach(function(tableName) {
                  chainer.add(self, 'dropTable', [ tableName, { cascade: true } ])
                })
 
                chainer
                  .runSerially()
                  .proxy(dropAllTablesEmitter, { events: ['sql'] })
                  .error(onError)
                  .success(function() {
                    self.emit('dropAllTables', null)
                    dropAllTablesEmitter.emit('success', null)
                  })
              }
            })
        })
    }).run()
  }
}