def get_sequences(self, model, num_children, shard_range): output = [] our_epoch = int(time.mktime(datetime(2012, 11, 1).timetuple()) * 1000) proc = """CREATE OR REPLACE FUNCTION next_sharded_id(varchar, int, OUT result bigint) AS $$ DECLARE sequence_name ALIAS FOR $1; shard_id ALIAS FOR $2; seq_id bigint; now_millis bigint; BEGIN SELECT nextval(sequence_name::regclass) % 1024 INTO seq_id; SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis; result := (now_millis - {our_epoch}) << 23; result := result | (shard_id << 10); result := result | (seq_id); END; $$ LANGUAGE PLPGSQL;""".format( our_epoch=our_epoch ) output.append(self.style.SQL_KEYWORD(proc)) for i in shard_range: child = generate_child_partition(model, i) output.append( self.style.SQL_KEYWORD("CREATE SEQUENCE ") + self.style.SQL_TABLE(get_sharded_id_sequence_name(child)) + ";" ) return output
def db_type(self, *args, **kwargs): if not hasattr(self.model, '_shards'): raise ValueError("ShardedAutoField must be used with a PartitionModel.") if self.model._shards.is_master: return "bigint" return "bigint DEFAULT next_sharded_id('%s'::varchar, %d)" % ( get_sharded_id_sequence_name(self.model), self.model._shards.num)
def create_sequence(self, created_models, **kwargs): # Sequence creation for production is handled by DDL scripts # (sqlpartition). This is needed to create sequences for # test models. if self.model not in created_models: return db_alias = self.model._shards.cluster for child in self.model._shards.nodes: cursor = connections[db_alias].cursor() sid = transaction.savepoint(db_alias) sequence_name = get_sharded_id_sequence_name(child) try: cursor.execute("CREATE SEQUENCE %s;" % sequence_name) except DatabaseError: transaction.savepoint_rollback(sid, using=db_alias) # Sequence must already exist, ensure it gets reset cursor.execute("SELECT setval('%s', 1, false)" % (sequence_name,)) else: print 'Created sequence %r on %r' % (sequence_name, db_alias) transaction.savepoint_commit(sid, using=db_alias) cursor.close()
def create_sequence(self, created_models, **kwargs): # Sequence creation for production is handled by DDL scripts # (sqlpartition). This is needed to create sequences for # test models. if self.model not in created_models: return db_alias = self.model._shards.cluster for child in self.model._shards.nodes: cursor = connections[db_alias].cursor() sid = transaction.savepoint(db_alias) sequence_name = get_sharded_id_sequence_name(child) try: cursor.execute("CREATE SEQUENCE %s;" % sequence_name) except DatabaseError: transaction.savepoint_rollback(sid, using=db_alias) # Sequence must already exist, ensure it gets reset cursor.execute("SELECT setval('%s', 1, false)" % (sequence_name, )) else: print 'Created sequence %r on %r' % (sequence_name, db_alias) transaction.savepoint_commit(sid, using=db_alias) cursor.close()