| 135 | } |
| 136 | |
| 137 | update(props) { |
| 138 | extend(this, props); |
| 139 | |
| 140 | if ("query_result" in props) { |
| 141 | this.status = ExecutionStatus.DONE; |
| 142 | this.deferred.onStatusChange(ExecutionStatus.DONE); |
| 143 | |
| 144 | const columnTypes = {}; |
| 145 | |
| 146 | // TODO: we should stop manipulating incoming data, and switch to relaying |
| 147 | // on the column type set by the backend. This logic is prone to errors, |
| 148 | // and better be removed. Kept for now, for backward compatability. |
| 149 | each(this.query_result.data.rows, (row) => { |
| 150 | forOwn(row, (v, k) => { |
| 151 | let newType = null; |
| 152 | if (isNumber(v)) { |
| 153 | newType = "float"; |
| 154 | } else if (isDateTime(v)) { |
| 155 | row[k] = moment.utc(v); |
| 156 | newType = "datetime"; |
| 157 | } else if (isString(v) && v.match(/^\d{4}-\d{2}-\d{2}$/)) { |
| 158 | row[k] = moment.utc(v); |
| 159 | newType = "date"; |
| 160 | } else if (typeof v === "object" && v !== null) { |
| 161 | row[k] = JSON.stringify(v); |
| 162 | } else { |
| 163 | newType = "string"; |
| 164 | } |
| 165 | |
| 166 | if (newType !== null) { |
| 167 | if (columnTypes[k] !== undefined && columnTypes[k] !== newType) { |
| 168 | columnTypes[k] = "string"; |
| 169 | } else { |
| 170 | columnTypes[k] = newType; |
| 171 | } |
| 172 | } |
| 173 | }); |
| 174 | }); |
| 175 | |
| 176 | each(this.query_result.data.columns, (column) => { |
| 177 | column.name = "" + column.name; |
| 178 | if (columnTypes[column.name]) { |
| 179 | if (column.type == null || column.type === "string") { |
| 180 | column.type = columnTypes[column.name]; |
| 181 | } |
| 182 | } |
| 183 | }); |
| 184 | |
| 185 | this.deferred.resolve(this); |
| 186 | } else if (this.job.status === 3 || this.job.status === 2) { |
| 187 | this.deferred.onStatusChange(ExecutionStatus.PROCESSING); |
| 188 | this.status = "processing"; |
| 189 | } else if (this.job.status === 4) { |
| 190 | this.status = statuses[this.job.status]; |
| 191 | this.deferred.reject(new QueryResultError(this.job.error)); |
| 192 | } else { |
| 193 | this.deferred.onStatusChange(undefined); |
| 194 | this.status = undefined; |