| 215 | self._callbacks.append((fn, args, kwargs)) |
| 216 | |
| 217 | def execute(self): |
| 218 | if self._executed and self.warn_multiple_exec: |
| 219 | msg = "Batch executed multiple times." |
| 220 | if self._context_entered: |
| 221 | msg += " If using the batch as a context manager, there is no need to call execute directly." |
| 222 | warn(msg) |
| 223 | self._executed = True |
| 224 | |
| 225 | if len(self.queries) == 0: |
| 226 | # Empty batch is a no-op |
| 227 | # except for callbacks |
| 228 | self._execute_callbacks() |
| 229 | return |
| 230 | |
| 231 | batch_type = None if self.batch_type is CBatchType.LOGGED else self.batch_type |
| 232 | opener = 'BEGIN ' + (str(batch_type) + ' ' if batch_type else '') + ' BATCH' |
| 233 | if self.timestamp: |
| 234 | |
| 235 | if isinstance(self.timestamp, int): |
| 236 | ts = self.timestamp |
| 237 | elif isinstance(self.timestamp, (datetime, timedelta)): |
| 238 | ts = self.timestamp |
| 239 | if isinstance(self.timestamp, timedelta): |
| 240 | ts += datetime.now() # Apply timedelta |
| 241 | ts = int(time.mktime(ts.timetuple()) * 1e+6 + ts.microsecond) |
| 242 | else: |
| 243 | raise ValueError("Batch expects a long, a timedelta, or a datetime") |
| 244 | |
| 245 | opener += ' USING TIMESTAMP {0}'.format(ts) |
| 246 | |
| 247 | query_list = [opener] |
| 248 | parameters = {} |
| 249 | ctx_counter = 0 |
| 250 | for query in self.queries: |
| 251 | query.update_context_id(ctx_counter) |
| 252 | ctx = query.get_context() |
| 253 | ctx_counter += len(ctx) |
| 254 | query_list.append(' ' + str(query)) |
| 255 | parameters.update(ctx) |
| 256 | |
| 257 | query_list.append('APPLY BATCH;') |
| 258 | |
| 259 | tmp = conn.execute('\n'.join(query_list), parameters, self._consistency, self._timeout, connection=self._connection) |
| 260 | check_applied(tmp) |
| 261 | |
| 262 | self.queries = [] |
| 263 | self._execute_callbacks() |
| 264 | |
| 265 | def __enter__(self): |
| 266 | self._context_entered = True |