Revision 4100e0ee

b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/alembic/versions/3b62b3f1bf6c_add_attributes_node_.py
1
"""add attributes node column
2

  
3
Revision ID: 3b62b3f1bf6c
4
Revises: 4c8ccdc58192
5
Create Date: 2013-07-04 13:11:01.842706
6

  
7
"""
8

  
9
# revision identifiers, used by Alembic.
10
revision = '3b62b3f1bf6c'
11
down_revision = '4c8ccdc58192'
12

  
13
from alembic import op
14
import sqlalchemy as sa
15
from sqlalchemy.sql import table, column, and_
16

  
17

  
18
def upgrade():
19
    op.add_column('attributes',
20
                  sa.Column('node', sa.Integer, default=0))
21
    op.add_column('attributes',
22
                  sa.Column('is_latest', sa.Boolean, default=True))
23

  
24
    n = table('nodes',
25
              column('node', sa.Integer),
26
              column('latest_version', sa.Integer))
27
    v = table('versions',
28
              column('node', sa.Integer),
29
              column('serial', sa.Integer))
30
    a = table('attributes',
31
              column('serial', sa.Integer),
32
              column('node', sa.Integer),
33
              column('is_latest', sa.Boolean))
34

  
35
    s = sa.select([v.c.node]).where(v.c.serial == a.c.serial)
36
    u = a.update().values({'node': s})
37
    op.execute(u)
38

  
39
    s = sa.select([v.c.serial == n.c.latest_version],
40
                  and_(a.c.node == n.c.node, a.c.serial == v.c.serial))
41
    u = a.update().values({'is_latest': s})
42
    op.execute(u)
43

  
44
    op.alter_column('attributes', 'node', nullable=False)
45
    op.alter_column('attributes', 'is_latest', nullable=False)
46

  
47
    op.create_index('idx_attributes_serial_node', 'attributes',
48
                    ['serial', 'node'])
49

  
50

  
51
def downgrade():
52
    op.drop_index('idx_attributes_serial_node')
53

  
54
    op.drop_column('attributes', 'is_latest')
55
    op.drop_column('attributes', 'node')
b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/node.py
35 35
from operator import itemgetter
36 36
from itertools import groupby
37 37

  
38
from sqlalchemy import Table, Integer, BigInteger, DECIMAL, Column, String, MetaData, ForeignKey
38
from sqlalchemy import (Table, Integer, BigInteger, DECIMAL, Boolean,
39
                        Column, String, MetaData, ForeignKey)
39 40
from sqlalchemy.types import Text
40 41
from sqlalchemy.schema import Index, Sequence
41 42
from sqlalchemy.sql import func, and_, or_, not_, null, select, bindparam, text, exists
......
180 181
    columns.append(Column('domain', String(256), primary_key=True))
181 182
    columns.append(Column('key', String(128), primary_key=True))
182 183
    columns.append(Column('value', String(256)))
184
    columns.append(Column('node', Integer, nullable=False, default=0))
185
    columns.append(Column('is_latest', Boolean, nullable=False, default=True))
183 186
    attributes = Table('attributes', metadata, *columns, mysql_engine='InnoDB')
184 187
    Index('idx_attributes_domain', attributes.c.domain)
188
    Index('idx_attributes_serial_node', attributes.c.serial, attributes.c.node)
185 189

  
186 190
    metadata.create_all(engine)
187 191
    return metadata.sorted_tables
......
865 869
        r.close()
866 870
        return l
867 871

  
868
    def attribute_set(self, serial, domain, items):
872
    def attribute_set(self, serial, domain, node, items, is_latest=True):
869 873
        """Set the attributes of the version specified by serial.
870 874
           Receive attributes as an iterable of (key, value) pairs.
871 875
        """
......
881 885
            rp.close()
882 886
            if rp.rowcount == 0:
883 887
                s = self.attributes.insert()
884
                s = s.values(serial=serial, domain=domain, key=k, value=v)
888
                s = s.values(serial=serial, domain=domain, node=node,
889
                             is_latest=is_latest, key=k, value=v)
885 890
                self.conn.execute(s).close()
886 891

  
887 892
    def attribute_del(self, serial, domain, keys=()):
......
906 911

  
907 912
    def attribute_copy(self, source, dest):
908 913
        s = select(
909
            [dest, self.attributes.c.domain,
910
                self.attributes.c.key, self.attributes.c.value],
914
            [dest, self.attributes.c.domain, self.attributes.c.node,
915
             self.attributes.c.key, self.attributes.c.value],
911 916
            self.attributes.c.serial == source)
912 917
        rp = self.conn.execute(s)
913 918
        attributes = rp.fetchall()
914 919
        rp.close()
915
        for dest, domain, k, v in attributes:
916
            #insert or replace
920
        for dest, domain, node, k, v in attributes:
921
            # insert or replace
917 922
            s = self.attributes.update().where(and_(
918 923
                self.attributes.c.serial == dest,
919 924
                self.attributes.c.domain == domain,
920 925
                self.attributes.c.key == k))
921
            rp = self.conn.execute(s, value=v)
926
            s = s.values(value=v)
927
            rp = self.conn.execute(s)
922 928
            rp.close()
923 929
            if rp.rowcount == 0:
924 930
                s = self.attributes.insert()
925
                values = {'serial': dest, 'domain': domain,
926
                          'key': k, 'value': v}
927
                self.conn.execute(s, values).close()
931
                s = s.values(serial=dest, domain=domain, node=node,
932
                             is_latest=True, key=k, value=v)
933
            self.conn.execute(s).close()
934

  
935
    def attribute_unset_is_latest(self, node, exclude):
936
        u = self.attributes.update().where(and_(
937
            self.attributes.c.node == node,
938
                     self.attributes.c.serial != exclude)).values(
939
                             {'is_latest': False})
940
        self.conn.execute(u)
928 941

  
929 942
    def latest_attribute_keys(self, parent, domain, before=inf, except_cluster=0, pathq=None):
930 943
        """Return a list with all keys pairs defined
......
1178 1191
        s = select([n.c.path, v.c.serial, v.c.node, v.c.hash, v.c.size,
1179 1192
                    v.c.type, v.c.source, v.c.mtime, v.c.muser, v.c.uuid,
1180 1193
                    v.c.checksum, v.c.cluster, a.c.key, a.c.value])
1181
        s = s.where(n.c.node == v.c.node)
1182
        s = s.where(n.c.latest_version == v.c.serial)
1183 1194
        if cluster:
1184 1195
            s = s.where(v.c.cluster == cluster)
1185 1196
        s = s.where(v.c.serial == a.c.serial)
1186 1197
        s = s.where(a.c.domain == domain)
1198
        s = s.where(a.c.node == n.c.node)
1199
        s = s.where(a.c.is_latest == True)
1187 1200
        if paths:
1188 1201
            s = s.where(n.c.path.in_(paths))
1189 1202

  
b/snf-pithos-backend/pithos/backends/modular.py
930 930
        if src_version_id is None:
931 931
            src_version_id = pre_version_id
932 932
        self._put_metadata_duplicate(
933
            src_version_id, dest_version_id, domain, meta, replace_meta)
933
            src_version_id, dest_version_id, domain, node, meta, replace_meta)
934 934

  
935 935
        del_size = self._apply_versioning(account, container, pre_version_id,
936 936
                                          update_statistics_ancestors_depth=1)
......
1352 1352
        dest_version_id, mtime = self.node.version_create(
1353 1353
            node, hash, size, type, src_version_id, user, uuid, checksum,
1354 1354
            cluster, update_statistics_ancestors_depth)
1355

  
1356
        self.node.attribute_unset_is_latest(node, dest_version_id)
1357

  
1355 1358
        return pre_version_id, dest_version_id
1356 1359

  
1357
    def _put_metadata_duplicate(self, src_version_id, dest_version_id, domain, meta, replace=False):
1360
    def _put_metadata_duplicate(self, src_version_id, dest_version_id, domain,
1361
                                node, meta, replace=False):
1358 1362
        if src_version_id is not None:
1359 1363
            self.node.attribute_copy(src_version_id, dest_version_id)
1360 1364
        if not replace:
1361 1365
            self.node.attribute_del(dest_version_id, domain, (
1362 1366
                k for k, v in meta.iteritems() if v == ''))
1363
            self.node.attribute_set(dest_version_id, domain, (
1367
            self.node.attribute_set(dest_version_id, domain, node, (
1364 1368
                (k, v) for k, v in meta.iteritems() if v != ''))
1365 1369
        else:
1366 1370
            self.node.attribute_del(dest_version_id, domain)
1367
            self.node.attribute_set(dest_version_id, domain, ((
1371
            self.node.attribute_set(dest_version_id, domain, node, ((
1368 1372
                k, v) for k, v in meta.iteritems()))
1369 1373

  
1370 1374
    def _put_metadata(self, user, node, domain, meta, replace=False,
......
1375 1379
            user, node,
1376 1380
            update_statistics_ancestors_depth=update_statistics_ancestors_depth)
1377 1381
        self._put_metadata_duplicate(
1378
            src_version_id, dest_version_id, domain, meta, replace)
1382
            src_version_id, dest_version_id, domain, node, meta, replace)
1379 1383
        return src_version_id, dest_version_id
1380 1384

  
1381 1385
    def _list_limits(self, listing, marker, limit):

Also available in: Unified diff