def prepare(query, params): # For every match of the form ":param_name", call marshal # on kwargs['param_name'] and replace that section of the query # with the result new, count = re.subn(_param_re, lambda m: marshal(params[m.group(1)[1:]]), query) if len(params) > count: raise cql.ProgrammingError("More keywords were provided than parameters") return new
def execute(self, cql_query, params={}): self.__checksock() self.rs_idx = 0 self.rowcount = 0 self.description = None try: prepared_q = self.prepare(cql_query, params) except KeyError, e: raise cql.ProgrammingError("Unmatched named substitution: " + "%s not given for %s" % (e, cql_query))
def prepare_query(self, query): if isinstance(query, unicode): raise ValueError("CQL query must be bytes, not unicode") prepared_q_text, paramnames = prepare_query(query) compressed_q, compression = self.compress_query_text(prepared_q_text) presult = self._connection.client.prepare_cql_query( compressed_q, compression) assert presult.count == len(paramnames) if presult.variable_types is None and presult.count > 0: raise cql.ProgrammingError( "Cassandra did not provide types for bound" " parameters. Prepared statements are only" " supported with cql3.") return PreparedQuery(query, presult.itemId, presult.variable_types, paramnames)
def prepare(query, params): """ For every match of the form ":param_name", call marshal on kwargs['param_name'] and replace that section of the query with the result """ def repl(match): name = match.group(1)[1:] if name in params: return marshal(params[name]) return ":%s" % name new, count = re.subn(_param_re, repl, query) if len(params) > count: raise cql.ProgrammingError("More keywords were provided " "than parameters") return new
def register_watcher(self, eventtype, cb): """ Request that any events of the given type be passed to the given callback when they arrive. Note that the callback may not be called immediately upon the arrival of the event packet; it may have to wait until something else waits on a result, or until wait_for_even() is called. If the event type has not been registered for already, this may block while a new REGISTER message is sent to the server. The available event types are in the cql.native.known_event_types list. When an event arrives, a dictionary will be passed to the callback with the info about the event. Some example result dictionaries: (For STATUS_CHANGE events:) {'changetype': u'DOWN', 'address': ('12.114.19.76', 8000)} (For TOPOLOGY_CHANGE events:) {'changetype': u'NEW_NODE', 'address': ('19.10.122.13', 8000)} """ if isinstance(eventtype, str): eventtype = eventtype.decode('utf8') try: watchers = self.event_watchers[eventtype] except KeyError: ans = self.wait_for_request( RegisterMessage(eventlist=(eventtype, ))) if isinstance(ans, ErrorMessage): raise cql.ProgrammingError("Server did not accept registration" " for %s events: %s" % (eventtype, ans.summarymsg())) watchers = self.event_watchers.setdefault(eventtype, []) watchers.append(cb)
class Cursor: _keyspace_re = re.compile("USE (\w+);?", re.I | re.M) _cfamily_re = re.compile("\s*SELECT\s+.+\s+FROM\s+[\']?(\w+)", re.I | re.M) _ddl_re = re.compile("\s*(CREATE|ALTER|DROP)\s+", re.I | re.M) def __init__(self, parent_connection): self.open_socket = True self.parent_connection = parent_connection self.description = None # A list of 7-tuples: # (column_name, type_code, none, none, # none, none, nulls_ok=True) # Populate on execute() self.arraysize = 1 self.rowcount = -1 # Populate on execute() self.compression = 'GZIP' self._query_ks = self.parent_connection.keyspace self._query_cf = None self.decoder = SchemaDecoder(self.__get_schema()) ### # Cursor API ### def close(self): self.open_socket = False def prepare(self, query, params): prepared_query = prepare(query, params) self._schema_update_needed = False # Snag the keyspace or column family and stash it for later use in # decoding columns. These regexes don't match every query, but the # current column family only needs to be current for SELECTs. match = Cursor._cfamily_re.match(prepared_query) if match: self._query_cf = match.group(1) return prepared_query match = Cursor._keyspace_re.match(prepared_query) if match: self._query_ks = match.group(1) return prepared_query # If this is a CREATE, then refresh the schema for decoding purposes. match = Cursor._ddl_re.match(prepared_query) if match: self._schema_update_needed = True return prepared_query def __get_schema(self): def columns(metadata): results = {} for col in metadata: results[col.name] = col.validation_class return results def column_families(cf_defs): d = {} for cf in cf_defs: d[cf.name] = { 'comparator': cf.comparator_type, 'default_validation_class': cf.default_validation_class, 'key_validation_class': cf.key_validation_class, 'columns': columns(cf.column_metadata), 'key_alias': cf.key_alias } return d schema = {} client = self.parent_connection.client for ksdef in client.describe_keyspaces(): schema[ksdef.name] = column_families(ksdef.cf_defs) return schema def execute(self, cql_query, params={}): self.__checksock() self.rs_idx = 0 self.rowcount = 0 self.description = None try: prepared_q = self.prepare(cql_query, params) except KeyError, e: raise cql.ProgrammingError("Unmatched named substitution: " + "%s not given for %s" % (e, cql_query)) if self.compression == 'GZIP': compressed_q = zlib.compress(prepared_q) else: compressed_q = prepared_q request_compression = getattr(Compression, self.compression) try: client = self.parent_connection.client response = client.execute_cql_query(compressed_q, request_compression) except InvalidRequestException, ire: raise cql.ProgrammingError("Bad Request: %s" % ire.why)
def make_reqid(self): if self.reqid_slots == 0: raise cql.ProgrammingError("Unable to acquire a stream id") slot = ctzb(self.reqid_slots) self.reqid_slots &= ~(1 << slot) return slot
def prepare_inline(self, query, params): try: return prepare_inline(query, params, self.cql_major_version) except KeyError, e: raise cql.ProgrammingError("Unmatched named substitution: " + "%s not given for %r" % (e, query))
def __checksock(self): if self._connection is None or not self._connection.open_socket: raise cql.ProgrammingError("Cursor has been closed.")
def handle_cql_execution_errors(self, executor, *args, **kwargs): try: return executor(*args, **kwargs) except InvalidRequestException, ire: raise cql.ProgrammingError("Bad Request: %s" % ire.why)