cubicweb/server/sources/native.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 28 Sep 2016 22:17:36 +0200
changeset 11750 18e7b9829471
parent 11430 1ea5ba74a13c
child 11756 60fed6272771
permissions -rw-r--r--
[sources] Drop source support_entity / support_relation source API this was used in the pre-datafeed area, it's not worth it anymore. Its only valid usage was in authentication to detect if the source was supporting CWUser, hence we now call it systematically and catch NotImplementedError.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
     1
# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5413
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    18
"""Adapters for native cubicweb sources.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
1952
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
    20
Notes:
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
    21
* extid (aka external id, the primary key of an entity in the external source
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
    22
  from which it comes from) are stored in a varchar column encoded as a base64
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
    23
  string. This is because it should actually be Bytes but we want an index on
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
    24
  it for fast querying.
5824
de9b7e88660e cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5751
diff changeset
    25
"""
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    26
from __future__ import print_function
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    27
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    28
__docformat__ = "restructuredtext en"
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
4900
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4893
diff changeset
    30
from threading import Lock
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 973
diff changeset
    31
from datetime import datetime
10580
5fbdbbe51867 [server/sources] add decode_extid method
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
    32
from base64 import b64encode
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
    33
from contextlib import contextmanager
9468
39b7a91a3f4c [repo] pylint cleanup, mainly of imports, with a bit of style
Julien Cristau <julien.cristau@logilab.fr>
parents: 9467
diff changeset
    34
from os.path import basename
6211
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
    35
import re
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
    36
import itertools
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
    37
import zipfile
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
    38
import logging
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
    39
import sys
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    40
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
    41
from six import PY2, text_type, binary_type, string_types
10609
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10602
diff changeset
    42
from six.moves import range, cPickle as pickle
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
    43
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
    44
from logilab.common.decorators import cached, clear_cache
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
    45
from logilab.common.configuration import Method
11060
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
    46
from logilab.common.shellutils import getlogin, ASK
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
    47
from logilab.database import get_db_helper, sqlgen
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
    49
from yams.schema import role_name
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
    50
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
    51
from cubicweb import (UnknownEid, AuthenticationError, ValidationError, Binary,
10446
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
    52
                      UniqueTogetherError, UndoTransactionException, ViolatedConstraint)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
    53
from cubicweb import transaction as tx, server, neg_role
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7922
diff changeset
    54
from cubicweb.utils import QueryCache
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    55
from cubicweb.schema import VIRTUAL_RTYPES
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
    56
from cubicweb.cwconfig import CubicWebNoAppConfiguration
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
    57
from cubicweb.server import hook
10200
cceb2c7c02f4 Use our version of schema2sql
Julien Cristau <julien.cristau@logilab.fr>
parents: 10187
diff changeset
    58
from cubicweb.server import schema2sql as y2sql
11091
29aebc1edd29 [repository] drop usage of no more necessary eschema_eid function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11005
diff changeset
    59
from cubicweb.server.utils import crypt_password, verify_and_update
2759
23d7a75693f8 R refactor backup and use tar.gz to store all sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2638
diff changeset
    60
from cubicweb.server.sqlutils import SQL_PREFIX, SQLAdapterMixIn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    61
from cubicweb.server.rqlannotation import set_qdata
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
    62
from cubicweb.server.hook import CleanupDeletedEidsCacheOp
7118
e094b3d4eb95 [server] move EditedEntity class to its own module, to avoid cyclic dependency when needed from e.g. session.py
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6957
diff changeset
    63
from cubicweb.server.edition import EditedEntity
2625
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
    64
from cubicweb.server.sources import AbstractSource, dbg_st_search, dbg_results
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
from cubicweb.server.sources.rql2sql import SQLGenerator
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
    66
from cubicweb.statsd_logger import statsd_timeit
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
2354
9b4bac626977 ability to map attributes to something else than usual cw mapping on sql generation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2310
diff changeset
    69
ATTR_MAP = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    70
NONSYSTEM_ETYPES = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    71
NONSYSTEM_RELATIONS = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
    73
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    74
class LogCursor(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    75
    def __init__(self, cursor):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    76
        self.cu = cursor
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    77
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    78
    def execute(self, query, args=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    81
        """
2593
16d9419a4a79 F: start to handle binary debug log level on the server side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2589
diff changeset
    82
        if server.DEBUG & server.DBG_SQL:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    83
            print('exec', query, args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    84
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    85
            self.cu.execute(str(query), args)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
    86
        except Exception as ex:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    87
            print("sql: %r\n args: %s\ndbms message: %r" % (
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    88
                query, args, ex.args[0]))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    89
            raise
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    90
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    91
    def fetchall(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    92
        return self.cu.fetchall()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    93
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    94
    def fetchone(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    95
        return self.cu.fetchone()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    96
2625
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
    97
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    98
def sql_or_clauses(sql, clauses):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    99
    select, restr = sql.split(' WHERE ', 1)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   100
    restrclauses = restr.split(' AND ')
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   101
    for clause in clauses:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   102
        restrclauses.remove(clause)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   103
    if restrclauses:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   104
        restr = '%s AND (%s)' % (' AND '.join(restrclauses),
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   105
                                 ' OR '.join(clauses))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   106
    else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   107
        restr = '(%s)' % ' OR '.join(clauses)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   108
    return '%s WHERE %s' % (select, restr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   109
9450
af4b93bc38a5 [multi-sources-removal] Drop deleted_entities system table and entities.mtime column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9448
diff changeset
   110
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   111
def rdef_table_column(rdef):
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   112
    """return table and column used to store the given relation definition in
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   113
    the database
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   114
    """
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   115
    return (SQL_PREFIX + str(rdef.subject),
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   116
            SQL_PREFIX + str(rdef.rtype))
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   117
9450
af4b93bc38a5 [multi-sources-removal] Drop deleted_entities system table and entities.mtime column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9448
diff changeset
   118
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   119
def rdef_physical_info(dbhelper, rdef):
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   120
    """return backend type and a boolean flag if NULL values should be allowed
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   121
    for a given relation definition
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   122
    """
11005
f8417bd135ed [server, hooks] allow callable in dbh.TYPE_MAPPING
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10915
diff changeset
   123
    if not rdef.object.final:
f8417bd135ed [server, hooks] allow callable in dbh.TYPE_MAPPING
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10915
diff changeset
   124
        return dbhelper.TYPE_MAPPING['Int']
11359
2da2dd60331c [sql gen] Explicitly name unique index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11351
diff changeset
   125
    coltype = y2sql.type_from_rdef(dbhelper, rdef)
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   126
    allownull = rdef.cardinality[0] != '1'
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   127
    return coltype, allownull
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   128
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   129
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   130
class _UndoException(Exception):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   131
    """something went wrong during undoing"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   132
7530
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   133
    def __unicode__(self):
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   134
        """Called by the unicode builtin; should return a Unicode object
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   135
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   136
        Type of _UndoException message must be `unicode` by design in CubicWeb.
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   137
        """
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   138
        assert isinstance(self.args[0], text_type)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   139
        return self.args[0]
7530
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   140
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   141
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   142
def _undo_check_relation_target(tentity, rdef, role):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   143
    """check linked entity has not been redirected for this relation"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   144
    card = rdef.role_cardinality(role)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   145
    if card in '?1' and tentity.related(rdef.rtype, role):
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   146
        msg = tentity._cw._(
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   147
            "Can't restore %(role)s relation %(rtype)s to entity %(eid)s which "
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   148
            "is already linked using this relation.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   149
        raise _UndoException(msg % {'role': neg_role(role),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   150
                                    'rtype': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   151
                                    'eid': tentity.eid})
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   152
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   153
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   154
def _undo_rel_info(cnx, subj, rtype, obj):
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   155
    entities = []
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   156
    for role, eid in (('subject', subj), ('object', obj)):
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   157
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   158
            entities.append(cnx.entity_from_eid(eid))
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   159
        except UnknownEid:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   160
            msg = cnx._(
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   161
                "Can't restore relation %(rtype)s, %(role)s entity %(eid)s"
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   162
                " doesn't exist anymore.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   163
            raise _UndoException(msg % {'role': cnx._(role),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   164
                                        'rtype': cnx._(rtype),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   165
                                        'eid': eid})
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   166
    sentity, oentity = entities
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   167
    try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   168
        rschema = cnx.vreg.schema.rschema(rtype)
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
   169
        rdef = rschema.rdefs[(sentity.cw_etype, oentity.cw_etype)]
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   170
    except KeyError:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   171
        msg = cnx._(
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   172
            "Can't restore relation %(rtype)s between %(subj)s and "
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   173
            "%(obj)s, that relation does not exists anymore in the "
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   174
            "schema.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   175
        raise _UndoException(msg % {'rtype': cnx._(rtype),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   176
                                    'subj': subj,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   177
                                    'obj': obj})
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   178
    return sentity, oentity, rdef
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   179
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   180
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   181
def _undo_has_later_transaction(cnx, eid):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   182
    return cnx.system_sql('''\
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   183
SELECT T.tx_uuid FROM transactions AS TREF, transactions AS T
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   184
WHERE TREF.tx_uuid='%(txuuid)s' AND T.tx_uuid!='%(txuuid)s'
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   185
AND T.tx_time>=TREF.tx_time
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   186
AND (EXISTS(SELECT 1 FROM tx_entity_actions AS TEA
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   187
            WHERE TEA.tx_uuid=T.tx_uuid AND TEA.eid=%(eid)s)
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   188
     OR EXISTS(SELECT 1 FROM tx_relation_actions as TRA
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   189
               WHERE TRA.tx_uuid=T.tx_uuid AND (
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   190
                   TRA.eid_from=%(eid)s OR TRA.eid_to=%(eid)s))
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   191
     )''' % {'txuuid': cnx.transaction_data['undoing_uuid'],
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   192
             'eid': eid}).fetchone()
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   193
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   194
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   195
class DefaultEidGenerator(object):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   196
    __slots__ = ('source', 'cnx', 'lock')
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   197
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   198
    def __init__(self, source):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   199
        self.source = source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   200
        self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   201
        self.lock = Lock()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   202
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   203
    def close(self):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   204
        if self.cnx:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   205
            self.cnx.close()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   206
        self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   207
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   208
    def create_eid(self, _cnx, count=1):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   209
        # lock needed to prevent 'Connection is busy with results for another
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   210
        # command (0)' errors with SQLServer
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   211
        assert count > 0
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   212
        with self.lock:
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   213
            return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   214
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   215
    def _create_eid(self, count):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   216
        # internal function doing the eid creation without locking.
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   217
        # needed for the recursive handling of disconnections (otherwise we
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   218
        # deadlock on self._eid_cnx_lock
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   219
        source = self.source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   220
        if self.cnx is None:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   221
            self.cnx = source.get_connection()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   222
        cnx = self.cnx
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   223
        try:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   224
            cursor = cnx.cursor()
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   225
            for sql in source.dbhelper.sqls_increment_numrange('entities_id_seq', count):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   226
                cursor.execute(sql)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   227
            eid = cursor.fetchone()[0]
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   228
        except (source.OperationalError, source.InterfaceError):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   229
            # FIXME: better detection of deconnection pb
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   230
            source.warning("trying to reconnect create eid connection")
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   231
            self.cnx = None
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   232
            return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   233
        except source.DbapiError as exc:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   234
            # We get this one with pyodbc and SQL Server when connection was reset
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   235
            if exc.args[0] == '08S01':
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   236
                source.warning("trying to reconnect create eid connection")
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   237
                self.cnx = None
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   238
                return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   239
            else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   240
                raise
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   241
        except Exception: # WTF?
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   242
            cnx.rollback()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   243
            self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   244
            source.exception('create eid failed in an unforeseen way on SQL statement %s', sql)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   245
            raise
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   246
        else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   247
            cnx.commit()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   248
            return eid
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   249
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   250
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   251
class SQLITEEidGenerator(object):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   252
    __slots__ = ('source', 'lock')
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   253
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   254
    def __init__(self, source):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   255
        self.source = source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   256
        self.lock = Lock()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   257
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   258
    def close(self):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   259
        pass
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   260
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   261
    def create_eid(self, cnx, count=1):
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   262
        assert count > 0
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   263
        source = self.source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   264
        with self.lock:
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   265
            for sql in source.dbhelper.sqls_increment_numrange('entities_id_seq', count):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   266
                cursor = source.doexec(cnx, sql)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   267
            return cursor.fetchone()[0]
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   268
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   269
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   270
class NativeSQLSource(SQLAdapterMixIn, AbstractSource):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
    """adapter for source using the native cubicweb schema (see below)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
    """
2354
9b4bac626977 ability to map attributes to something else than usual cw mapping on sql generation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2310
diff changeset
   273
    sqlgen_class = SQLGenerator
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
    options = (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   275
        ('db-driver',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   276
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   277
          'default': 'postgres',
5423
e15abfdcce38 backport default into stable: stable is now cw 3.8
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5397 5421
diff changeset
   278
          # XXX use choice type
10221
17ad882a211f [doc] Don't pretend we know cubicweb runs on mysql
Julien Cristau <julien.cristau@logilab.fr>
parents: 10209
diff changeset
   279
          'help': 'database driver (postgres, sqlite, sqlserver2005)',
6201
cf445fcaf8fe [c-c create] ask for database driver by default
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6128
diff changeset
   280
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   282
        ('db-host',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   283
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
          'default': '',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   285
          'help': 'database host',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   286
          'group': 'native-source', 'level': 1,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   287
          }),
2566
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   288
        ('db-port',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   289
         {'type': 'string',
2566
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   290
          'default': '',
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   291
          'help': 'database port',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   292
          'group': 'native-source', 'level': 1,
2566
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   293
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   294
        ('db-name',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   295
         {'type': 'string',
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   296
          'default': Method('default_instance_id'),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   297
          'help': 'database name',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   298
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
          }),
10125
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   300
        ('db-namespace',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   301
         {'type': 'string',
10125
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   302
          'default': '',
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   303
          'help': 'database namespace (schema) name',
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   304
          'group': 'native-source', 'level': 1,
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   305
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   306
        ('db-user',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   307
         {'type': 'string',
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   308
          'default': CubicWebNoAppConfiguration.mode == 'user' and getlogin() or 'cubicweb',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   309
          'help': 'database user',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   310
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   311
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   312
        ('db-password',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   313
         {'type': 'password',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   314
          'default': '',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   315
          'help': 'database password',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   316
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   317
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   318
        ('db-encoding',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   319
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   320
          'default': 'utf8',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   321
          'help': 'database encoding',
5323
329b4f6d18b4 [config] with lgc >= 0.50, option's dict inputlevel becomes level
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5217
diff changeset
   322
          'group': 'native-source', 'level': 1,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   323
          }),
5413
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   324
        ('db-extra-arguments',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   325
         {'type': 'string',
5413
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   326
          'default': '',
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   327
          'help': 'set to "Trusted_Connection" if you are using SQLServer and '
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   328
                  'want trusted authentication for the database connection',
5515
513af9be9e37 [config] rename remaining inputlevel to level in option definitions, as expected by lgc >= 0.50
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5426
diff changeset
   329
          'group': 'native-source', 'level': 2,
5413
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   330
          }),
9724
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   331
        ('db-statement-timeout',
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   332
         {'type': 'int',
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   333
          'default': 0,
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   334
          'help': 'sql statement timeout, in milliseconds (postgres only)',
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   335
          'group': 'native-source', 'level': 2,
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   336
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
    )
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   338
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   339
    def __init__(self, repo, source_config, *args, **kwargs):
9724
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   340
        SQLAdapterMixIn.__init__(self, source_config, repairing=repo.config.repairing)
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   341
        self.authentifiers = [LoginPasswordAuthentifier(self)]
6849
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
   342
        if repo.config['allow-email-login']:
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
   343
            self.authentifiers.insert(0, EmailPasswordAuthentifier(self))
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   344
        AbstractSource.__init__(self, repo, source_config, *args, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   345
        # sql generator
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   346
        self._rql_sqlgen = self.sqlgen_class(self.schema, self.dbhelper,
4831
c5aec27c1bf7 [repo] use logilab.db instead of lgc.adbh/lgc.db/lgc.sqlgen/indexer, test new date extranction functions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4829
diff changeset
   347
                                             ATTR_MAP.copy())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   348
        # full text index helper
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   349
        self.do_fti = not repo.config['delay-full-text-indexation']
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   350
        # sql queries cache
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7922
diff changeset
   351
        self._cache = QueryCache(repo.config['rql-cache-size'])
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   352
        # (etype, attr) / storage mapping
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   353
        self._storages = {}
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   354
        self.binary_to_str = self.dbhelper.dbapi_module.binary_to_str
5649
a07dee204187 fix unit tests by not using the new create_eid implementation with sqlite
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5645
diff changeset
   355
        if self.dbdriver == 'sqlite':
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   356
            self.eid_generator = SQLITEEidGenerator(self)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   357
        else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   358
            self.eid_generator = DefaultEidGenerator(self)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   359
        self.create_eid = self.eid_generator.create_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   360
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   361
    def check_config(self, source_entity):
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   362
        """check configuration of source entity"""
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   363
        if source_entity.host_config:
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   364
            msg = source_entity._cw._('the system source has its configuration '
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   365
                                      'stored on the file-system')
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   366
            raise ValidationError(source_entity.eid, {role_name('config', 'subject'): msg})
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   367
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   368
    def add_authentifier(self, authentifier):
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   369
        self.authentifiers.append(authentifier)
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   370
        authentifier.source = self
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   371
        authentifier.set_schema(self.schema)
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   372
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   373
    def reset_caches(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   374
        """method called during test to reset potential source caches"""
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7922
diff changeset
   375
        self._cache = QueryCache(self.repo.config['rql-cache-size'])
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   376
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   377
    def clear_eid_cache(self, eid, etype):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   378
        """clear potential caches for the given eid"""
2610
2933cc6bf9ad [F native source] fix attempts to clear cache key
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2593
diff changeset
   379
        self._cache.pop('Any X WHERE X eid %s, X is %s' % (eid, etype), None)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   380
        self._cache.pop('Any X WHERE X eid %s' % eid, None)
2610
2933cc6bf9ad [F native source] fix attempts to clear cache key
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2593
diff changeset
   381
        self._cache.pop('Any %s' % eid, None)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   382
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   383
    @statsd_timeit
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   384
    def sqlexec(self, cnx, sql, args=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   385
        """execute the query and return its result"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   386
        return self.process_result(self.doexec(cnx, sql, args))
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   387
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   388
    def init_creating(self, cnxset=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   389
        # check full text index availibility
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   390
        if self.do_fti:
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   391
            if cnxset is None:
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   392
                _cnxset = self.repo._get_cnxset()
6724
24bf6f181d0e [pyro source] store pyro source mapping file into the database
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6427
diff changeset
   393
            else:
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   394
                _cnxset = cnxset
9463
d62e13eba033 [multi-sources-removal] Simplify ConnectionsSet internal structures and public methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9452
diff changeset
   395
            if not self.dbhelper.has_fti_table(_cnxset.cu):
4825
cdd979ae1b57 fix name error fixed in wrong branch
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4818
diff changeset
   396
                if not self.repo.config.creating:
4810
3055dc7a7c88 don't issue critical warning about missing text index when we're creating the instance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4807
diff changeset
   397
                    self.critical('no text index table')
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   398
                self.do_fti = False
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   399
            if cnxset is None:
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   400
                _cnxset.cnxset_freed()
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   401
                self.repo._free_cnxset(_cnxset)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   402
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   403
    def backup(self, backupfile, confirm, format='native'):
2759
23d7a75693f8 R refactor backup and use tar.gz to store all sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2638
diff changeset
   404
        """method called to create a backup of the source's data"""
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   405
        if format == 'portable':
8947
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   406
            # ensure the schema is the one stored in the database: if repository
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   407
            # started in quick_start mode, the file system's one has been loaded
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   408
            # so force reload
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   409
            if self.repo.config.quick_start:
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   410
                self.repo.set_schema(self.repo.deserialize_schema(),
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   411
                                     resetvreg=False)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   412
            helper = DatabaseIndependentBackupRestore(self)
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   413
            self.close_source_connections()
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   414
            try:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   415
                helper.backup(backupfile)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   416
            finally:
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   417
                self.open_source_connections()
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   418
        elif format == 'native':
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   419
            self.close_source_connections()
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   420
            try:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   421
                self.backup_to_file(backupfile, confirm)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   422
            finally:
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   423
                self.open_source_connections()
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   424
        else:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   425
            raise ValueError('Unknown format %r' % format)
2493
9806571ea790 major refactoring of database dump/restore:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
   426
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   427
    def restore(self, backupfile, confirm, drop, format='native'):
2493
9806571ea790 major refactoring of database dump/restore:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
   428
        """method called to restore a backup of source's data"""
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   429
        if self.repo.config.init_cnxset_pool:
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   430
            self.close_source_connections()
2759
23d7a75693f8 R refactor backup and use tar.gz to store all sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2638
diff changeset
   431
        try:
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   432
            if format == 'portable':
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   433
                helper = DatabaseIndependentBackupRestore(self)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   434
                helper.restore(backupfile)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   435
            elif format == 'native':
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   436
                self.restore_from_file(backupfile, confirm, drop=drop)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   437
            else:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   438
                raise ValueError('Unknown format %r' % format)
2759
23d7a75693f8 R refactor backup and use tar.gz to store all sources
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2638
diff changeset
   439
        finally:
7398
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   440
            if self.repo.config.init_cnxset_pool:
26695dd703d8 [repository api] definitly kill usage of word 'pool' to refer to connections set used by a session
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   441
                self.open_source_connections()
2493
9806571ea790 major refactoring of database dump/restore:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
   442
6957
ffda12be2e9f [repository] #1460066: backport datafeed cube as cubicweb source
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6945
diff changeset
   443
    def init(self, activated, source_entity):
7543
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   444
        try:
7786
18a366267612 [repo] use smarter query to check asource presence on startup (closes #1922099)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7754
diff changeset
   445
            # test if 'asource' column exists
7839
daf46963f4fe ensure the test for asource column won't crash on SQLServer (closes #1949621)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7787
diff changeset
   446
            query = self.dbhelper.sql_add_limit_offset('SELECT asource FROM entities', 1)
daf46963f4fe ensure the test for asource column won't crash on SQLServer (closes #1949621)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7787
diff changeset
   447
            source_entity._cw.system_sql(query)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   448
        except Exception:
7543
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   449
            self.eid_type_source = self.eid_type_source_pre_131
9131
b3ad80aa645f fix migration from pre-3.13.1 versions (closes #2846978)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9130
diff changeset
   450
        super(NativeSQLSource, self).init(activated, source_entity)
b3ad80aa645f fix migration from pre-3.13.1 versions (closes #2846978)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9130
diff changeset
   451
        self.init_creating(source_entity._cw.cnxset)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   452
5749
b4393b681f7a [repo] on repository shutdown, we've to close the new eid creation connection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5729
diff changeset
   453
    def shutdown(self):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   454
        self.eid_generator.close()
5749
b4393b681f7a [repo] on repository shutdown, we've to close the new eid creation connection
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5729
diff changeset
   455
9492
c7fc56eecd1a English typography
Dimitri Papadopoulos <dimitri.papadopoulos@cea.fr>
parents: 9375
diff changeset
   456
    # XXX deprecates [un]map_attribute?
5013
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   457
    def map_attribute(self, etype, attr, cb, sourcedb=True):
10095
200bd6a601dc [warnings] put an end to warnings in the sqlite driver over `str` being sent instead of unicode strings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10086
diff changeset
   458
        self._rql_sqlgen.attr_map[u'%s.%s' % (etype, attr)] = (cb, sourcedb)
2493
9806571ea790 major refactoring of database dump/restore:
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2476
diff changeset
   459
4512
e7ac20bf3629 unset_attribute_storage, for testing purpose at least
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   460
    def unmap_attribute(self, etype, attr):
10095
200bd6a601dc [warnings] put an end to warnings in the sqlite driver over `str` being sent instead of unicode strings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10086
diff changeset
   461
        self._rql_sqlgen.attr_map.pop(u'%s.%s' % (etype, attr), None)
4512
e7ac20bf3629 unset_attribute_storage, for testing purpose at least
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   462
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   463
    def set_storage(self, etype, attr, storage):
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   464
        storage_dict = self._storages.setdefault(etype, {})
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   465
        storage_dict[attr] = storage
5013
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   466
        self.map_attribute(etype, attr,
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   467
                           storage.callback, storage.is_source_callback)
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   468
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   469
    def unset_storage(self, etype, attr):
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   470
        self._storages[etype].pop(attr)
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   471
        # if etype has no storage left, remove the entry
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   472
        if not self._storages[etype]:
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   473
            del self._storages[etype]
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   474
        self.unmap_attribute(etype, attr)
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   475
5397
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   476
    def storage(self, etype, attr):
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   477
        """return the storage for the given entity type / attribute
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   478
        """
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   479
        try:
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   480
            return self._storages[etype][attr]
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   481
        except KeyError:
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   482
            raise Exception('no custom storage set for %s.%s' % (etype, attr))
cdbf823450aa [bfss] new storage_changed migration action to move an attribute to a custom storage. Closes #893941
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5323
diff changeset
   483
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
    # ISource interface #######################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   485
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   486
    @statsd_timeit
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   487
    def compile_rql(self, rql, sols):
3240
8604a15995d1 refactor so that rql rewriter may be used outside the server. Enhance it to be usable for RRQLExpression as well
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3041
diff changeset
   488
        rqlst = self.repo.vreg.rqlhelper.parse(rql)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   489
        rqlst.restricted_vars = ()
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   490
        rqlst.children[0].solutions = sols
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   491
        self.repo.querier.sqlgen_annotate(rqlst)
438
69b79faefa94 need_intersect test and fixes
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   492
        set_qdata(self.schema.rschema, rqlst, ())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   493
        return rqlst
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   494
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   495
    def set_schema(self, schema):
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   496
        """set the instance'schema"""
7954
a3d3220669d6 [cache] replace lgc.cache with something more appropriate (closes #1921713)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 7922
diff changeset
   497
        self._cache = QueryCache(self.repo.config['rql-cache-size'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   498
        self.cache_hit, self.cache_miss, self.no_cache = 0, 0, 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   499
        self.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   500
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   501
            self._rql_sqlgen.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   502
        except AttributeError:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   503
            pass  # __init__
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   504
        for authentifier in self.authentifiers:
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   505
            authentifier.set_schema(self.schema)
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   506
        clear_cache(self, 'need_fti_indexation')
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   507
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   508
    @statsd_timeit
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
   509
    def authenticate(self, cnx, login, **kwargs):
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   510
        """return CWUser eid for the given login and other authentication
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   511
        information found in kwargs, else raise `AuthenticationError`
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
        """
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   513
        for authentifier in self.authentifiers:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   514
            try:
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
   515
                return authentifier.authenticate(cnx, login, **kwargs)
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   516
            except AuthenticationError:
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   517
                continue
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
   518
        raise AuthenticationError()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   519
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11135
diff changeset
   520
    def syntax_tree_search(self, cnx, union, args=None, cachekey=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
        """return result from this source for a rql query (actually from
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   522
        a rql syntax tree and a solution dictionary mapping each used
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   523
        variable to a possible type). If cachekey is given, the query
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   524
        necessary to fetch the results (but not the results themselves)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   525
        may be cached using this key.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   526
        """
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11135
diff changeset
   527
        assert dbg_st_search(self.uri, union, args, cachekey)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   528
        # remember number of actually selected term (sql generation may append some)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   529
        if cachekey is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   530
            self.no_cache += 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   531
            # generate sql query if we are able to do so (not supported types...)
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11135
diff changeset
   532
            sql, qargs, cbs = self._rql_sqlgen.generate(union, args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   533
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   534
            # sql may be cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   535
            try:
5013
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   536
                sql, qargs, cbs = self._cache[cachekey]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   537
                self.cache_hit += 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   538
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   539
                self.cache_miss += 1
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11135
diff changeset
   540
                sql, qargs, cbs = self._rql_sqlgen.generate(union, args)
5013
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   541
                self._cache[cachekey] = sql, qargs, cbs
ad91f93bbb93 [source storage] refactor source sql generation and results handling to allow repository side callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5011
diff changeset
   542
        args = self.merge_args(args, qargs)
10612
84468b90e9c1 [py3k] basestring → six.string_types
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10609
diff changeset
   543
        assert isinstance(sql, string_types), repr(sql)
11430
1ea5ba74a13c [native] Use cnx.system_sql instead of doexec method in syntax_tree_search
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11429
diff changeset
   544
        cursor = cnx.system_sql(sql, args)
10086
98bc2ca1a816 [source/native] session -> cnx
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10074
diff changeset
   545
        results = self.process_result(cursor, cnx, cbs)
2625
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
   546
        assert dbg_results(results)
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
   547
        return results
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   548
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   549
    @contextmanager
10550
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   550
    def _fixup_cw(self, cnx, entity):
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   551
        _cw = entity._cw
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   552
        entity._cw = cnx
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   553
        try:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   554
            yield
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   555
        finally:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   556
            entity._cw = _cw
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   557
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   558
    @contextmanager
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   559
    def _storage_handler(self, cnx, entity, event):
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   560
        # 1/ memorize values as they are before the storage is called.
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   561
        #    For instance, the BFSStorage will replace the `data`
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   562
        #    binary value with a Binary containing the destination path
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   563
        #    on the filesystem. To make the entity.data usage absolutely
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   564
        #    transparent, we'll have to reset entity.data to its binary
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   565
        #    value once the SQL query will be executed
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   566
        restore_values = []
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   567
        if isinstance(entity, list):
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   568
            entities = entity
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   569
        else:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   570
            entities = [entity]
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   571
        etype = entities[0].__regid__
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   572
        for attr, storage in self._storages.get(etype, {}).items():
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   573
            for entity in entities:
10550
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   574
                with self._fixup_cw(cnx, entity):
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   575
                    if event == 'deleted':
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   576
                        storage.entity_deleted(entity, attr)
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   577
                    else:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   578
                        edited = entity.cw_edited
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   579
                        if attr in edited:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   580
                            handler = getattr(storage, 'entity_%s' % event)
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   581
                            to_restore = handler(entity, attr)
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   582
                            restore_values.append((entity, attr, to_restore))
5128
e5d300d75519 [python] take care to this detail of @contextmanager: if an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5107
diff changeset
   583
        try:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   584
            yield  # 2/ execute the source's instructions
5128
e5d300d75519 [python] take care to this detail of @contextmanager: if an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5107
diff changeset
   585
        finally:
e5d300d75519 [python] take care to this detail of @contextmanager: if an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5107
diff changeset
   586
            # 3/ restore original values
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   587
            for entity, attr, value in restore_values:
6142
8bc6eac1fac1 [session] cleanup hook / operation / entity edition api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6128
diff changeset
   588
                entity.cw_edited.edited_attribute(attr, value)
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   589
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   590
    def add_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   591
        """add a new entity to the source"""
10550
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   592
        with self._storage_handler(cnx, entity, 'added'):
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   593
            attrs = self.preprocess_entity(entity)
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
   594
            sql = self.sqlgen.insert(SQL_PREFIX + entity.cw_etype, attrs)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   595
            self.doexec(cnx, sql, attrs)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   596
            if cnx.ertype_supports_undo(entity.cw_etype):
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   597
                self._record_tx_action(cnx, 'tx_entity_actions', u'C',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   598
                                       etype=text_type(entity.cw_etype), eid=entity.eid)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   599
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   600
    def update_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   601
        """replace an entity in the source"""
10550
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   602
        with self._storage_handler(cnx, entity, 'updated'):
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   603
            attrs = self.preprocess_entity(entity)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   604
            if cnx.ertype_supports_undo(entity.cw_etype):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   605
                changes = self._save_attrs(cnx, entity, attrs)
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   606
                self._record_tx_action(cnx, 'tx_entity_actions', u'U',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   607
                                       etype=text_type(entity.cw_etype), eid=entity.eid,
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   608
                                       changes=self._binary(pickle.dumps(changes)))
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
   609
            sql = self.sqlgen.update(SQL_PREFIX + entity.cw_etype, attrs,
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   610
                                     ['cw_eid'])
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   611
            self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   612
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   613
    def delete_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   614
        """delete an entity from the source"""
10550
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   615
        with self._storage_handler(cnx, entity, 'deleted'):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   616
            if cnx.ertype_supports_undo(entity.cw_etype):
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   617
                attrs = [SQL_PREFIX + r.type
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   618
                         for r in entity.e_schema.subject_relations()
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   619
                         if (r.final or r.inlined) and r not in VIRTUAL_RTYPES]
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   620
                changes = self._save_attrs(cnx, entity, attrs)
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   621
                self._record_tx_action(cnx, 'tx_entity_actions', u'D',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   622
                                       etype=text_type(entity.cw_etype), eid=entity.eid,
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
   623
                                       changes=self._binary(pickle.dumps(changes)))
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   624
            attrs = {'cw_eid': entity.eid}
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
   625
            sql = self.sqlgen.delete(SQL_PREFIX + entity.cw_etype, attrs)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   626
            self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   627
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   628
    def add_relation(self, cnx, subject, rtype, object, inlined=False):
5072
072ae171aeb0 [cleanup] style fixes, add nodes, 0.2 cents refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5071
diff changeset
   629
        """add a relation to the source"""
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   630
        self._add_relations(cnx, rtype, [(subject, object)], inlined)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   631
        if cnx.ertype_supports_undo(rtype):
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   632
            self._record_tx_action(cnx, 'tx_relation_actions', u'A',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   633
                                   eid_from=subject, rtype=text_type(rtype), eid_to=object)
5072
072ae171aeb0 [cleanup] style fixes, add nodes, 0.2 cents refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5071
diff changeset
   634
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   635
    def add_relations(self, cnx, rtype, subj_obj_list, inlined=False):
7237
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7202
diff changeset
   636
        """add a relations to the source"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   637
        self._add_relations(cnx, rtype, subj_obj_list, inlined)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   638
        if cnx.ertype_supports_undo(rtype):
7237
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7202
diff changeset
   639
            for subject, object in subj_obj_list:
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   640
                self._record_tx_action(cnx, 'tx_relation_actions', u'A',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   641
                                       eid_from=subject, rtype=text_type(rtype), eid_to=object)
7551
2d4ba5b984dc cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7530
diff changeset
   642
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   643
    def _add_relations(self, cnx, rtype, subj_obj_list, inlined=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   644
        """add a relation to the source"""
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   645
        sql = []
4818
9f9bfbcdecfd le patch massiveimport a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4810
diff changeset
   646
        if inlined is False:
7237
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7202
diff changeset
   647
            attrs = [{'eid_from': subject, 'eid_to': object}
9f619715665b [server] improve the speed of setting relations between entities (closes #1625257)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7202
diff changeset
   648
                     for subject, object in subj_obj_list]
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   649
            sql.append((self.sqlgen.insert('%s_relation' % rtype, attrs[0]), attrs))
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   650
        else:  # used by data import
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   651
            etypes = {}
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   652
            for subject, object in subj_obj_list:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   653
                etype = cnx.entity_metas(subject)['type']
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   654
                if etype in etypes:
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   655
                    etypes[etype].append((subject, object))
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   656
                else:
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   657
                    etypes[etype] = [(subject, object)]
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10651
diff changeset
   658
            for subj_etype, subj_obj_list in etypes.items():
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   659
                attrs = [{'cw_eid': subject, SQL_PREFIX + rtype: object}
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   660
                         for subject, object in subj_obj_list]
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   661
                sql.append((self.sqlgen.update(SQL_PREFIX + etype, attrs[0],
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   662
                                               ['cw_eid']),
7243
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   663
                            attrs))
9ab01bf84eac fix bad handling of inlined relations when entities of different etypes are passed as subject to add_relations
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7237
diff changeset
   664
        for statement, attrs in sql:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   665
            self.doexecmany(cnx, statement, attrs)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   666
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   667
    def delete_relation(self, cnx, subject, rtype, object):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   668
        """delete a relation from the source"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   669
        rschema = self.schema.rschema(rtype)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   670
        self._delete_relation(cnx, subject, rtype, object, rschema.inlined)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   671
        if cnx.ertype_supports_undo(rtype):
10264
d5403de0792b [server] use unicode wherever appropriate in transaction/undo related methods
Julien Cristau <julien.cristau@logilab.fr>
parents: 10221
diff changeset
   672
            self._record_tx_action(cnx, 'tx_relation_actions', u'R',
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   673
                                   eid_from=subject, rtype=text_type(rtype), eid_to=object)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   674
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   675
    def _delete_relation(self, cnx, subject, rtype, object, inlined=False):
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   676
        """delete a relation from the source"""
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   677
        if inlined:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   678
            table = SQL_PREFIX + cnx.entity_metas(subject)['type']
1251
af40e615dc89 introduce a 'cw_' prefix on entity table and column names so we don't conflict with sql or DBMS specific keywords
sylvain.thenault@logilab.fr
parents: 1079
diff changeset
   679
            column = SQL_PREFIX + rtype
af40e615dc89 introduce a 'cw_' prefix on entity table and column names so we don't conflict with sql or DBMS specific keywords
sylvain.thenault@logilab.fr
parents: 1079
diff changeset
   680
            sql = 'UPDATE %s SET %s=NULL WHERE %seid=%%(eid)s' % (table, column,
af40e615dc89 introduce a 'cw_' prefix on entity table and column names so we don't conflict with sql or DBMS specific keywords
sylvain.thenault@logilab.fr
parents: 1079
diff changeset
   681
                                                                  SQL_PREFIX)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   682
            attrs = {'eid': subject}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   683
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
            attrs = {'eid_from': subject, 'eid_to': object}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   685
            sql = self.sqlgen.delete('%s_relation' % rtype, attrs)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   686
        self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   687
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   688
    @statsd_timeit
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   689
    def doexec(self, cnx, query, args=None, rollback=True):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   690
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   691
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   693
        cursor = cnx.cnxset.cu
2593
16d9419a4a79 F: start to handle binary debug log level on the server side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2589
diff changeset
   694
        if server.DEBUG & server.DBG_SQL:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
   695
            print('exec', query, args, cnx.cnxset.cnx)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   696
        try:
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9492
diff changeset
   697
            # str(query) to avoid error if it's a unicode string
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   698
            cursor.execute(str(query), args)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
   699
        except Exception as ex:
4682
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   700
            if self.repo.config.mode != 'test':
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   701
                # during test we get those message when trying to alter sqlite
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   702
                # db schema
10178
4b33246cb43c [native] Change SQL errors log level.
Christophe de Vienne <christophe@unlish.com>
parents: 10076
diff changeset
   703
                self.info("sql: %r\n args: %s\ndbms message: %r",
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   704
                          query, args, ex.args[0])
2618
ff9b0d5bd884 [F repo sqlite schema changes] don't rollback on potentially expected schema changes failure
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2611
diff changeset
   705
            if rollback:
ff9b0d5bd884 [F repo sqlite schema changes] don't rollback on potentially expected schema changes failure
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2611
diff changeset
   706
                try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   707
                    cnx.cnxset.rollback()
4692
11a040e2601c [test] also hide this message during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4682
diff changeset
   708
                    if self.repo.config.mode != 'test':
10178
4b33246cb43c [native] Change SQL errors log level.
Christophe de Vienne <christophe@unlish.com>
parents: 10076
diff changeset
   709
                        self.debug('transaction has been rolled back')
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
   710
                except Exception as ex:
2618
ff9b0d5bd884 [F repo sqlite schema changes] don't rollback on potentially expected schema changes failure
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2611
diff changeset
   711
                    pass
6211
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
   712
            if ex.__class__.__name__ == 'IntegrityError':
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
   713
                # need string comparison because of various backends
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
   714
                for arg in ex.args:
9375
8e88576787c3 [schema] fix unique together index handling
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
   715
                    # postgres, sqlserver
8e88576787c3 [schema] fix unique together index handling
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
   716
                    mo = re.search("unique_[a-z0-9]{32}", arg)
6211
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
   717
                    if mo is not None:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   718
                        raise UniqueTogetherError(cnx, cstrname=mo.group(0))
10053
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   719
                    # old sqlite
10329
f92823a66f18 [sqlite] Fix integrity error parsing
Christophe de Vienne <christophe@unlish.com>
parents: 10272
diff changeset
   720
                    mo = re.search('columns? (.*) (?:is|are) not unique', arg)
6247
f7cb092d2296 unique_together: recast exception raised by sqlite
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6211
diff changeset
   721
                    if mo is not None: # sqlite in use
8820
dbffb6959564 server/source/native: fix wrong usage of .lstrip that produce garbled error messages (closes #2777641)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8546
diff changeset
   722
                        # we left chop the 'cw_' prefix of attribute names
dbffb6959564 server/source/native: fix wrong usage of .lstrip that produce garbled error messages (closes #2777641)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8546
diff changeset
   723
                        rtypes = [c.strip()[3:]
dbffb6959564 server/source/native: fix wrong usage of .lstrip that produce garbled error messages (closes #2777641)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8546
diff changeset
   724
                                  for c in mo.group(1).split(',')]
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   725
                        raise UniqueTogetherError(cnx, rtypes=rtypes)
10053
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   726
                    # sqlite after http://www.sqlite.org/cgi/src/info/c80e229dd9c1230a
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   727
                    if arg.startswith('UNIQUE constraint failed:'):
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   728
                        # message looks like: "UNIQUE constraint failed: foo.cw_bar, foo.cw_baz"
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   729
                        # so drop the prefix, split on comma, drop the tablenames, and drop "cw_"
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   730
                        columns = arg.split(':', 1)[1].split(',')
079b5279a2cd [server] Handle unique constraint violations under recent sqlite
Julien Cristau <julien.cristau@logilab.fr>
parents: 10052
diff changeset
   731
                        rtypes = [c.split('.', 1)[1].strip()[3:] for c in columns]
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   732
                        raise UniqueTogetherError(cnx, rtypes=rtypes)
10446
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   733
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   734
                    mo = re.search('"cstr[a-f0-9]{32}"', arg)
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   735
                    if mo is not None:
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   736
                        # postgresql
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   737
                        raise ViolatedConstraint(cnx, cstrname=mo.group(0)[1:-1])
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   738
                    if arg.startswith('CHECK constraint failed:'):
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   739
                        # sqlite3 (new)
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   740
                        raise ViolatedConstraint(cnx, cstrname=arg.split(':', 1)[1].strip())
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   741
                    mo = re.match('^constraint (cstr.*) failed$', arg)
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   742
                    if mo is not None:
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   743
                        # sqlite3 (old)
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   744
                        raise ViolatedConstraint(cnx, cstrname=mo.group(1))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   745
            raise
2306
95da5d9f0870 give session to doexec so it's able to rollback the connection on unexpected error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2072
diff changeset
   746
        return cursor
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   747
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   748
    @statsd_timeit
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   749
    def doexecmany(self, cnx, query, args):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   751
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   752
        """
2593
16d9419a4a79 F: start to handle binary debug log level on the server side
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2589
diff changeset
   753
        if server.DEBUG & server.DBG_SQL:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
   754
            print('execmany', query, 'with', len(args), 'arguments', cnx.cnxset.cnx)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   755
        cursor = cnx.cnxset.cu
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   756
        try:
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9492
diff changeset
   757
            # str(query) to avoid error if it's a unicode string
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   758
            cursor.executemany(str(query), args)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
   759
        except Exception as ex:
4682
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   760
            if self.repo.config.mode != 'test':
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   761
                # during test we get those message when trying to alter sqlite
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   762
                # db schema
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   763
                self.critical("sql many: %r\n args: %s\ndbms message: %r",
4994901b7379 don't issue critical message when trying to alter sqlite db during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4517
diff changeset
   764
                              query, args, ex.args[0])
2306
95da5d9f0870 give session to doexec so it's able to rollback the connection on unexpected error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2072
diff changeset
   765
            try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   766
                cnx.cnxset.rollback()
4692
11a040e2601c [test] also hide this message during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4682
diff changeset
   767
                if self.repo.config.mode != 'test':
9267
24d9b86dfa54 spelling: rollbacked -> rolled back
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9131
diff changeset
   768
                    self.critical('transaction has been rolled back')
7645
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   769
            except Exception:
2306
95da5d9f0870 give session to doexec so it's able to rollback the connection on unexpected error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2072
diff changeset
   770
                pass
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   771
            raise
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   772
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   773
    # short cut to method requiring advanced db helper usage ##################
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   774
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   775
    def update_rdef_column(self, cnx, rdef):
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   776
        """update physical column for a relation definition (final or inlined)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   777
        """
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   778
        table, column = rdef_table_column(rdef)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   779
        coltype, allownull = rdef_physical_info(self.dbhelper, rdef)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   780
        if not self.dbhelper.alter_column_support:
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   781
            self.error("backend can't alter %s.%s to %s%s", table, column, coltype,
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   782
                       not allownull and 'NOT NULL' or '')
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   783
            return
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   784
        self.dbhelper.change_col_type(LogCursor(cnx.cnxset.cu),
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   785
                                      table, column, coltype, allownull)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   786
        self.info('altered %s.%s: now %s%s', table, column, coltype,
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   787
                  not allownull and 'NOT NULL' or '')
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   788
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   789
    def update_rdef_null_allowed(self, cnx, rdef):
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   790
        """update NULL / NOT NULL of physical column for a relation definition
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   791
        (final or inlined)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   792
        """
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   793
        if not self.dbhelper.alter_column_support:
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   794
            # not supported (and NOT NULL not set by yams in that case, so no
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   795
            # worry)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   796
            return
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   797
        table, column = rdef_table_column(rdef)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   798
        coltype, allownull = rdef_physical_info(self.dbhelper, rdef)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   799
        self.dbhelper.set_null_allowed(LogCursor(cnx.cnxset.cu),
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   800
                                       table, column, coltype, allownull)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   801
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   802
    def update_rdef_indexed(self, cnx, rdef):
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   803
        table, column = rdef_table_column(rdef)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   804
        if rdef.indexed:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   805
            self.create_index(cnx, table, column)
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   806
        else:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   807
            self.drop_index(cnx, table, column)
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   808
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   809
    def update_rdef_unique(self, cnx, rdef):
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   810
        table, column = rdef_table_column(rdef)
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   811
        if rdef.constraint_by_type('UniqueConstraint'):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   812
            self.create_index(cnx, table, column, unique=True)
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   813
        else:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   814
            self.drop_index(cnx, table, column, unique=True)
5891
99024ad59223 [schema migration] import refactoring to fix #1109558 and enhances things on the way
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5849
diff changeset
   815
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   816
    def create_index(self, cnx, table, column, unique=False):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   817
        cursor = LogCursor(cnx.cnxset.cu)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   818
        self.dbhelper.create_index(cursor, table, column, unique)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   819
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   820
    def drop_index(self, cnx, table, column, unique=False):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   821
        cursor = LogCursor(cnx.cnxset.cu)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
        self.dbhelper.drop_index(cursor, table, column, unique)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
    # system source interface #################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   825
10366
38c7598b5c61 [connection] remove the `mode` attribute
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10365
diff changeset
   826
    def _eid_type_source(self, cnx, eid, sql):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   827
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   828
            res = self.doexec(cnx, sql).fetchone()
7646
91a984ba420f [native source] fix bug introduced in 7645:cb2459aaa7d7: fetchone() may return None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7645
diff changeset
   829
            if res is not None:
91a984ba420f [native source] fix bug introduced in 7645:cb2459aaa7d7: fetchone() may return None
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7645
diff changeset
   830
                return res
7645
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   831
        except Exception:
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   832
            self.exception('failed to query entities table for eid %s', eid)
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   833
        raise UnknownEid(eid)
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   834
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   835
    def eid_type_source(self, cnx, eid):  # pylint: disable=E0202
10575
036f5964e6fe [server/sources] fix docstring for eid_type_source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
   836
        """return a tuple (type, extid, source) for the entity with id <eid>"""
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9468
diff changeset
   837
        sql = 'SELECT type, extid, asource FROM entities WHERE eid=%s' % eid
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   838
        res = self._eid_type_source(cnx, eid, sql)
10580
5fbdbbe51867 [server/sources] add decode_extid method
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
   839
        if not isinstance(res, list):
5fbdbbe51867 [server/sources] add decode_extid method
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
   840
            res = list(res)
5fbdbbe51867 [server/sources] add decode_extid method
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
   841
        res[-2] = self.decode_extid(res[-2])
7543
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   842
        return res
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   843
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   844
    def eid_type_source_pre_131(self, cnx, eid):
10575
036f5964e6fe [server/sources] fix docstring for eid_type_source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10550
diff changeset
   845
        """return a tuple (type, extid, source) for the entity with id <eid>"""
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9468
diff changeset
   846
        sql = 'SELECT type, extid FROM entities WHERE eid=%s' % eid
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   847
        res = self._eid_type_source(cnx, eid, sql)
7543
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   848
        if not isinstance(res, list):
570522300e22 [ms, entity metas] add 'actual source' to entities table / base entity metadata cache. Closes #1767090
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7536
diff changeset
   849
            res = list(res)
10915
cf800aa43f48 [server/sources] fix name error in eid_type_source_pre_131
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10769
diff changeset
   850
        res[-1] = self.decode_extid(res[-1])
10270
1ae64186af94 [migration] reorder system tables / meta-schema migration into bootstrap_migration
Erica Marco <erica.marco@logilab.fr>
parents: 10197
diff changeset
   851
        res.append("system")
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   852
        return res
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   853
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   854
    def extid2eid(self, cnx, extid):
1952
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
   855
        """get eid from an external id. Return None if no record found."""
10758
a34edc1057c0 [datafeed] use explicit encode/decode instead of casting to str
Julien Cristau <julien.cristau@logilab.fr>
parents: 10676
diff changeset
   856
        assert isinstance(extid, binary_type)
a34edc1057c0 [datafeed] use explicit encode/decode instead of casting to str
Julien Cristau <julien.cristau@logilab.fr>
parents: 10676
diff changeset
   857
        args = {'x': b64encode(extid).decode('ascii')}
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   858
        cursor = self.doexec(cnx,
9469
032825bbacab [multi-sources-removal] Drop entities.source column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9468
diff changeset
   859
                             'SELECT eid FROM entities WHERE extid=%(x)s',
10209
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   860
                             args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   861
        # XXX testing rowcount cause strange bug with sqlite, results are there
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   862
        #     but rowcount is 0
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   863
        #if cursor.rowcount > 0:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   864
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   865
            result = cursor.fetchone()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   866
            if result:
1954
9b20f3504af8 cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1952
diff changeset
   867
                return result[0]
7645
cb2459aaa7d7 [source] closes #1816412: try to reconnect to dbms if connection is reset in eid_type_source()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 7562
diff changeset
   868
        except Exception:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   869
            pass
10209
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   870
        cursor = self.doexec(cnx,
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   871
                             'SELECT eid FROM moved_entities WHERE extid=%(x)s',
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   872
                             args)
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   873
        try:
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   874
            result = cursor.fetchone()
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   875
            if result:
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   876
                # entity was moved to the system source, return negative
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   877
                # number to tell the external source to ignore it
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   878
                return -result[0]
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   879
        except Exception:
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
   880
            pass
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   881
        return None
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   882
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   883
    def _handle_is_relation_sql(self, cnx, sql, attrs):
8625
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   884
        """ Handler for specific is_relation sql that may be
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   885
        overwritten in some stores"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   886
        self.doexec(cnx, sql % attrs)
8625
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   887
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   888
    _handle_insert_entity_sql = doexec
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   889
    _handle_is_instance_of_sql = _handle_source_relation_sql = _handle_is_relation_sql
7ee0752178e5 [dataimport] Add SQL Store for faster import - works ONLY with Postgres for now, as it requires "copy from" command - closes #2410822
Vincent Michel <vincent.michel@logilab.fr>
parents: 8573
diff changeset
   890
9664
5ef5494b6b0b [repository] complete argument is no more needed since we have no more 'true' multisource.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9611
diff changeset
   891
    def add_info(self, cnx, entity, source, extid):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   892
        """add type and source info for an eid into the system table"""
9802
9f815b1f2516 [repository,tests] use the new connection api (part 1/2)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9770
diff changeset
   893
        assert cnx.cnxset is not None
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   894
        # begin by inserting eid/type/source/extid into the entities table
1952
8e19c813750d fix extid handling: ensure encoded string is given, and store them as base64 (see note in native.py).
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1792
diff changeset
   895
        if extid is not None:
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   896
            assert isinstance(extid, binary_type)
10758
a34edc1057c0 [datafeed] use explicit encode/decode instead of casting to str
Julien Cristau <julien.cristau@logilab.fr>
parents: 10676
diff changeset
   897
            extid = b64encode(extid).decode('ascii')
a34edc1057c0 [datafeed] use explicit encode/decode instead of casting to str
Julien Cristau <julien.cristau@logilab.fr>
parents: 10676
diff changeset
   898
        attrs = {'type': text_type(entity.cw_etype), 'eid': entity.eid, 'extid': extid,
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   899
                 'asource': text_type(source.uri)}
9802
9f815b1f2516 [repository,tests] use the new connection api (part 1/2)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9770
diff changeset
   900
        self._handle_insert_entity_sql(cnx, self.sqlgen.insert('entities', attrs), attrs)
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   901
        # insert core relations: is, is_instance_of and cw_source
11091
29aebc1edd29 [repository] drop usage of no more necessary eschema_eid function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11005
diff changeset
   902
29aebc1edd29 [repository] drop usage of no more necessary eschema_eid function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11005
diff changeset
   903
        if entity.e_schema.eid is not None:  # else schema has not yet been serialized
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   904
            self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   905
                cnx, 'INSERT INTO is_relation(eid_from,eid_to) VALUES (%s,%s)',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   906
                (entity.eid, entity.e_schema.eid))
6851
824d5b6eae7f [repo] kill no more needed 'recreate' feature
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6849
diff changeset
   907
            for eschema in entity.e_schema.ancestors() + [entity.e_schema]:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   908
                self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   909
                    cnx,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   910
                    'INSERT INTO is_instance_of_relation(eid_from,eid_to) VALUES (%s,%s)',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   911
                    (entity.eid, eschema.eid))
11135
421520f4d516 [server] remove some pre 3.10 compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11129
diff changeset
   912
        if source.eid is not None:  # else the source has not yet been inserted
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   913
            self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   914
                cnx, 'INSERT INTO cw_source_relation(eid_from,eid_to) VALUES (%s,%s)',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   915
                (entity.eid, source.eid))
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   916
        # now we can update the full text index
10631
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
   917
        if self.need_fti_indexation(entity.cw_etype):
9802
9f815b1f2516 [repository,tests] use the new connection api (part 1/2)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9770
diff changeset
   918
            self.index_entity(cnx, entity=entity)
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   919
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   920
    def update_info(self, cnx, entity, need_fti_update):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   921
        """mark entity as being modified, fulltext reindex if needed"""
10631
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
   922
        if need_fti_update:
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   923
            # reindex the entity only if this query is updating at least
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
   924
            # one indexable attribute
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   925
            self.index_entity(cnx, entity=entity)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   926
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   927
    def delete_info_multi(self, cnx, entities):
7501
2983dd24494a [repository] refactor/cleanup entity deletion methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   928
        """delete system information on deletion of a list of entities with the
2983dd24494a [repository] refactor/cleanup entity deletion methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   929
        same etype and belinging to the same source
2983dd24494a [repository] refactor/cleanup entity deletion methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   930
5067
adc2122eed03 [repo] more efficient eid cache operations handling based on set_operation; refactor
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5061
diff changeset
   931
        * update the fti
7501
2983dd24494a [repository] refactor/cleanup entity deletion methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   932
        * remove record from the `entities` table
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   933
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   934
        self.fti_unindex_entities(cnx, entities)
11351
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   935
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   936
        # sqlserver is limited on the array size, the limit can occur starting
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   937
        # from > 10000 item, so we process by batch of 10000
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   938
        count = len(entities)
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   939
        batch_size = 10000
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   940
        for i in range(0, count, batch_size):
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   941
            in_eid = ",".join(str(entities[index].eid)
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   942
                              for index in range(i, min(i + batch_size, count)))
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   943
            attrs = {'eid': '(%s)' % (in_eid,)}
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   944
            self.doexec(cnx, self.sqlgen.delete_many('entities', attrs), attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   945
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   946
    # undo support #############################################################
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   947
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   948
    def undoable_transactions(self, cnx, ueid=None, **actionfilters):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
   949
        """See :class:`cubicweb.repoapi.Connection.undoable_transactions`"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   950
        # force filtering to connection's user if not a manager
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   951
        if not cnx.user.is_in_group('managers'):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   952
            ueid = cnx.user.eid
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   953
        restr = {}
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   954
        if ueid is not None:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   955
            restr['tx_user'] = ueid
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   956
        sql = self.sqlgen.select('transactions', restr, ('tx_uuid', 'tx_time', 'tx_user'))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   957
        if actionfilters:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   958
            # we will need subqueries to filter transactions according to
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   959
            # actions done
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   960
            tearestr = {}  # filters on the tx_entity_actions table
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   961
            trarestr = {}  # filters on the tx_relation_actions table
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   962
            genrestr = {}  # generic filters, appliyable to both table
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   963
            # unless public explicitly set to false, we only consider public
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   964
            # actions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   965
            if actionfilters.pop('public', True):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   966
                genrestr['txa_public'] = True
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   967
            # put additional filters in trarestr and/or tearestr
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10651
diff changeset
   968
            for key, val in actionfilters.items():
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   969
                if key == 'etype':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   970
                    # filtering on etype implies filtering on entity actions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   971
                    # only, and with no eid specified
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   972
                    assert actionfilters.get('action', 'C') in 'CUD'
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   973
                    assert 'eid' not in actionfilters
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   974
                    tearestr['etype'] = text_type(val)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   975
                elif key == 'eid':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   976
                    # eid filter may apply to 'eid' of tx_entity_actions or to
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   977
                    # 'eid_from' OR 'eid_to' of tx_relation_actions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   978
                    if actionfilters.get('action', 'C') in 'CUD':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   979
                        tearestr['eid'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   980
                    if actionfilters.get('action', 'A') in 'AR':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   981
                        trarestr['eid_from'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   982
                        trarestr['eid_to'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   983
                elif key == 'action':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   984
                    if val in 'CUD':
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   985
                        tearestr['txa_action'] = text_type(val)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   986
                    else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   987
                        assert val in 'AR'
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
   988
                        trarestr['txa_action'] = text_type(val)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   989
                else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   990
                    raise AssertionError('unknow filter %s' % key)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   991
            assert trarestr or tearestr, "can't only filter on 'public'"
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   992
            subqsqls = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   993
            # append subqueries to the original query, using EXISTS()
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   994
            if trarestr or (genrestr and not tearestr):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   995
                trarestr.update(genrestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   996
                trasql = self.sqlgen.select('tx_relation_actions', trarestr, ('1',))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   997
                if 'eid_from' in trarestr:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   998
                    # replace AND by OR between eid_from/eid_to restriction
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   999
                    trasql = sql_or_clauses(trasql, ['eid_from = %(eid_from)s',
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1000
                                                     'eid_to = %(eid_to)s'])
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1001
                trasql += ' AND transactions.tx_uuid=tx_relation_actions.tx_uuid'
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1002
                subqsqls.append('EXISTS(%s)' % trasql)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1003
            if tearestr or (genrestr and not trarestr):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1004
                tearestr.update(genrestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1005
                teasql = self.sqlgen.select('tx_entity_actions', tearestr, ('1',))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1006
                teasql += ' AND transactions.tx_uuid=tx_entity_actions.tx_uuid'
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1007
                subqsqls.append('EXISTS(%s)' % teasql)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1008
            if restr:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1009
                sql += ' AND %s' % ' OR '.join(subqsqls)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1010
            else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1011
                sql += ' WHERE %s' % ' OR '.join(subqsqls)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1012
            restr.update(trarestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1013
            restr.update(tearestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1014
        # we want results ordered by transaction's time descendant
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1015
        sql += ' ORDER BY tx_time DESC'
10365
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1016
        cu = self.doexec(cnx, sql, restr)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1017
        # turn results into transaction objects
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1018
        return [tx.Transaction(cnx, *args) for args in cu.fetchall()]
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1019
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1020
    def tx_info(self, cnx, txuuid):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
  1021
        """See :class:`cubicweb.repoapi.Connection.transaction_info`"""
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1022
        return tx.Transaction(cnx, txuuid, *self._tx_info(cnx, text_type(txuuid)))
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1023
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1024
    def tx_actions(self, cnx, txuuid, public):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
  1025
        """See :class:`cubicweb.repoapi.Connection.transaction_actions`"""
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1026
        txuuid = text_type(txuuid)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1027
        self._tx_info(cnx, txuuid)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1028
        restr = {'tx_uuid': txuuid}
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1029
        if public:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1030
            restr['txa_public'] = True
5072
072ae171aeb0 [cleanup] style fixes, add nodes, 0.2 cents refactorings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5071
diff changeset
  1031
        # XXX use generator to avoid loading everything in memory?
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1032
        sql = self.sqlgen.select('tx_entity_actions', restr,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1033
                                 ('txa_action', 'txa_public', 'txa_order',
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1034
                                  'etype', 'eid', 'changes'))
11429
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1035
        cu = self.doexec(cnx, sql, restr)
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1036
        actions = [tx.EntityAction(a, p, o, et, e, c and pickle.loads(self.binary_to_str(c)))
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1037
                   for a, p, o, et, e, c in cu.fetchall()]
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1038
        sql = self.sqlgen.select('tx_relation_actions', restr,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1039
                                 ('txa_action', 'txa_public', 'txa_order',
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1040
                                  'rtype', 'eid_from', 'eid_to'))
11429
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1041
        cu = self.doexec(cnx, sql, restr)
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
  1042
        actions += [tx.RelationAction(*args) for args in cu.fetchall()]
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1043
        return sorted(actions, key=lambda x: x.order)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1044
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1045
    def undo_transaction(self, cnx, txuuid):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
  1046
        """See :class:`cubicweb.repoapi.Connection.undo_transaction`
5071
8631bb9f6e73 [undo] during undoing, call hooks in the [active]integrity and undo categories
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5070
diff changeset
  1047
8631bb9f6e73 [undo] during undoing, call hooks in the [active]integrity and undo categories
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5070
diff changeset
  1048
        important note: while undoing of a transaction, only hooks in the
8631bb9f6e73 [undo] during undoing, call hooks in the [active]integrity and undo categories
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5070
diff changeset
  1049
        'integrity', 'activeintegrity' and 'undo' categories are called.
8631bb9f6e73 [undo] during undoing, call hooks in the [active]integrity and undo categories
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5070
diff changeset
  1050
        """
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1051
        errors = []
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1052
        cnx.transaction_data['undoing_uuid'] = txuuid
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1053
        with cnx.deny_all_hooks_but('integrity', 'activeintegrity', 'undo'):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1054
            with cnx.security_enabled(read=False):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1055
                for action in reversed(self.tx_actions(cnx, txuuid, False)):
4943
7f5b83578fec disable security when undoing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4913
diff changeset
  1056
                    undomethod = getattr(self, '_undo_%s' % action.action.lower())
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1057
                    errors += undomethod(cnx, action)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1058
        # remove the transactions record
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1059
        self.doexec(cnx,
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1060
                    "DELETE FROM transactions WHERE tx_uuid='%s'" % txuuid)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1061
        if errors:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1062
            raise UndoTransactionException(txuuid, errors)
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1063
        else:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1064
            return
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1065
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1066
    def start_undoable_transaction(self, cnx, uuid):
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1067
        """connection callback to insert a transaction record in the transactions
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1068
        table when some undoable transaction is started
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1069
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1070
        ueid = cnx.user.eid
7922
d307c3817782 [repository] use utcnow instead of now for some internal timetamps (closes #1988458)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7879
diff changeset
  1071
        attrs = {'tx_uuid': uuid, 'tx_user': ueid, 'tx_time': datetime.utcnow()}
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1072
        self.doexec(cnx, self.sqlgen.insert('transactions', attrs), attrs)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1073
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1074
    def _save_attrs(self, cnx, entity, attrs):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1075
        """return a pickleable dictionary containing current values for given
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1076
        attributes of the entity
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1077
        """
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1078
        restr = {'cw_eid': entity.eid}
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
  1079
        sql = self.sqlgen.select(SQL_PREFIX + entity.cw_etype, restr, attrs)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1080
        cu = self.doexec(cnx, sql, restr)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1081
        values = dict(zip(attrs, cu.fetchone()))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1082
        # ensure backend specific binary are converted back to string
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1083
        eschema = entity.e_schema
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1084
        for column in attrs:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1085
            # [3:] remove 'cw_' prefix
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1086
            attr = column[3:]
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1087
            if not eschema.subjrels[attr].final:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1088
                continue
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1089
            if eschema.destination(attr) in ('Password', 'Bytes'):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1090
                value = values[column]
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1091
                if value is not None:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1092
                    values[column] = self.binary_to_str(value)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1093
        return values
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1094
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1095
    def _record_tx_action(self, cnx, table, action, **kwargs):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1096
        """record a transaction action in the given table (either
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1097
        'tx_entity_actions' or 'tx_relation_action')
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1098
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1099
        kwargs['tx_uuid'] = cnx.transaction_uuid()
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1100
        kwargs['txa_action'] = action
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1101
        kwargs['txa_order'] = cnx.transaction_inc_action_counter()
10351
91e63306e277 [connection] replace .running_dbapi_query with .hooks_in_progress
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10301
diff changeset
  1102
        kwargs['txa_public'] = not cnx.hooks_in_progress
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1103
        self.doexec(cnx, self.sqlgen.insert(table, kwargs), kwargs)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1104
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1105
    def _tx_info(self, cnx, txuuid):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1106
        """return transaction's time and user of the transaction with the given uuid.
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1107
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1108
        raise `NoSuchTransaction` if there is no such transaction of if the
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1109
        connection's user isn't allowed to see it.
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1110
        """
10365
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1111
        restr = {'tx_uuid': txuuid}
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1112
        sql = self.sqlgen.select('transactions', restr,
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1113
                                 ('tx_time', 'tx_user'))
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1114
        cu = self.doexec(cnx, sql, restr)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1115
        try:
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1116
            time, ueid = cu.fetchone()
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1117
        except TypeError:
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1118
            raise tx.NoSuchTransaction(txuuid)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1119
        if not (cnx.user.is_in_group('managers')
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1120
                or cnx.user.eid == ueid):
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1121
            raise tx.NoSuchTransaction(txuuid)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1122
        return time, ueid
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1123
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1124
    def _reedit_entity(self, entity, changes, err):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1125
        cnx = entity._cw
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1126
        eid = entity.eid
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1127
        entity.cw_edited = edited = EditedEntity(entity)
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1128
        # check for schema changes, entities linked through inlined relation
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1129
        # still exists, rewrap binary values
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1130
        eschema = entity.e_schema
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1131
        getrschema = eschema.subjrels
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1132
        for column, value in changes.items():
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1133
            rtype = column[len(SQL_PREFIX):]
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1134
            if rtype == "eid":
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1135
                continue  # XXX should even `eid` be stored in action changes?
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1136
            try:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1137
                rschema = getrschema[rtype]
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1138
            except KeyError:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1139
                err(cnx._("can't restore relation %(rtype)s of entity %(eid)s, "
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1140
                          "this relation does not exist in the schema anymore.")
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1141
                    % {'rtype': rtype, 'eid': eid})
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1142
            if not rschema.final:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1143
                if not rschema.inlined:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1144
                    assert value is None
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1145
                # rschema is an inlined relation
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1146
                elif value is not None:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1147
                    # not a deletion: we must put something in edited
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1148
                    try:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1149
                        entity._cw.entity_from_eid(value)  # check target exists
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1150
                        edited[rtype] = value
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1151
                    except UnknownEid:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1152
                        err(cnx._("can't restore entity %(eid)s of type %(eschema)s, "
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1153
                                  "target of %(rtype)s (eid %(value)s) does not exist any longer")
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1154
                            % locals())
10206
0ecd61f4bd37 [undo] when we can't undo an inlined relation change, point at None, not a broken eid
Julien Cristau <julien.cristau@logilab.fr>
parents: 10203
diff changeset
  1155
                        changes[column] = None
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1156
            elif eschema.destination(rtype) in ('Bytes', 'Password'):
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1157
                changes[column] = self._binary(value)
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1158
                edited[rtype] = Binary(value)
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1159
            elif PY2 and isinstance(value, str):
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1160
                edited[rtype] = text_type(value, cnx.encoding, 'replace')
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1161
            else:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1162
                edited[rtype] = value
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1163
        # This must only be done after init_entitiy_caches : defered in calling functions
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1164
        # edited.check()
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1165
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1166
    def _undo_d(self, cnx, action):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1167
        """undo an entity deletion"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1168
        errors = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1169
        err = errors.append
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1170
        eid = action.eid
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1171
        etype = action.etype
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1172
        # get an entity instance
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1173
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1174
            entity = self.repo.vreg['etypes'].etype_class(etype)(cnx)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1175
        except Exception:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1176
            err("can't restore entity %s of type %s, type no more supported"
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1177
                % (eid, etype))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1178
            return errors
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1179
        self._reedit_entity(entity, action.changes, err)
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1180
        entity.eid = eid
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1181
        cnx.repo.init_entity_caches(cnx, entity, self)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1182
        entity.cw_edited.check()
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1183
        self.repo.hm.call_hooks('before_add_entity', cnx, entity=entity)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1184
        # restore the entity
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1185
        action.changes['cw_eid'] = eid
10203
1443fe643a38 [server] change order of entities table modification vs entity creation/deletion
Julien Cristau <julien.cristau@logilab.fr>
parents: 10200
diff changeset
  1186
        # restore record in entities (will update fti if needed)
1443fe643a38 [server] change order of entities table modification vs entity creation/deletion
Julien Cristau <julien.cristau@logilab.fr>
parents: 10200
diff changeset
  1187
        self.add_info(cnx, entity, self, None)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1188
        sql = self.sqlgen.insert(SQL_PREFIX + etype, action.changes)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1189
        self.doexec(cnx, sql, action.changes)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1190
        self.repo.hm.call_hooks('after_add_entity', cnx, entity=entity)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1191
        return errors
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1192
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1193
    def _undo_r(self, cnx, action):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1194
        """undo a relation removal"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1195
        errors = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1196
        subj, rtype, obj = action.eid_from, action.rtype, action.eid_to
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1197
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1198
            sentity, oentity, rdef = _undo_rel_info(cnx, subj, rtype, obj)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
  1199
        except _UndoException as ex:
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1200
            errors.append(text_type(ex))
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1201
        else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1202
            for role, entity in (('subject', sentity),
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1203
                                 ('object', oentity)):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1204
                try:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1205
                    _undo_check_relation_target(entity, rdef, role)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
  1206
                except _UndoException as ex:
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1207
                    errors.append(text_type(ex))
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1208
                    continue
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1209
        if not errors:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1210
            self.repo.hm.call_hooks('before_add_relation', cnx,
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1211
                                    eidfrom=subj, rtype=rtype, eidto=obj)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1212
            # add relation in the database
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1213
            self._add_relations(cnx, rtype, [(subj, obj)], rdef.rtype.inlined)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1214
            # set related cache
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1215
            cnx.update_rel_cache_add(subj, rtype, obj, rdef.rtype.symmetric)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1216
            self.repo.hm.call_hooks('after_add_relation', cnx,
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1217
                                    eidfrom=subj, rtype=rtype, eidto=obj)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1218
        return errors
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1219
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1220
    def _undo_c(self, cnx, action):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1221
        """undo an entity creation"""
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1222
        eid = action.eid
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1223
        # XXX done to avoid fetching all remaining relation for the entity
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1224
        # we should find an efficient way to do this (keeping current veolidf
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1225
        # massive deletion performance)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1226
        if _undo_has_later_transaction(cnx, eid):
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1227
            msg = cnx._('some later transaction(s) touch entity, undo them first')
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1228
            raise ValidationError(eid, {None: msg})
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1229
        etype = action.etype
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1230
        # get an entity instance
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1231
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1232
            entity = self.repo.vreg['etypes'].etype_class(etype)(cnx)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1233
        except Exception:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1234
            return [cnx._(
5098
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1235
                "Can't undo creation of entity %(eid)s of type %(etype)s, type "
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1236
                "no more supported" % {'eid': eid, 'etype': etype})]
5557
1a534c596bff [entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5556
diff changeset
  1237
        entity.eid = eid
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1238
        # for proper eid/type cache update
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1239
        CleanupDeletedEidsCacheOp.get_instance(cnx).add_data(eid)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1240
        self.repo.hm.call_hooks('before_delete_entity', cnx, entity=entity)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1241
        # remove is / is_instance_of which are added using sql by hooks, hence
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1242
        # unvisible as transaction action
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1243
        self.doexec(cnx, 'DELETE FROM is_relation WHERE eid_from=%s' % eid)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1244
        self.doexec(cnx, 'DELETE FROM is_instance_of_relation WHERE eid_from=%s' % eid)
10183
ff93dad2ae3a [undo] fix deletion of cw_source relation
Julien Cristau <julien.cristau@logilab.fr>
parents: 10178
diff changeset
  1245
        self.doexec(cnx, 'DELETE FROM cw_source_relation WHERE eid_from=%s' % eid)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1246
        # XXX check removal of inlined relation?
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1247
        # delete the entity
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1248
        attrs = {'cw_eid': eid}
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
  1249
        sql = self.sqlgen.delete(SQL_PREFIX + entity.cw_etype, attrs)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1250
        self.doexec(cnx, sql, attrs)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1251
        # remove record from entities (will update fti if needed)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1252
        self.delete_info_multi(cnx, [entity])
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1253
        self.repo.hm.call_hooks('after_delete_entity', cnx, entity=entity)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1254
        return ()
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1255
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1256
    def _undo_u(self, cnx, action):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1257
        """undo an entity update"""
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1258
        errors = []
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1259
        err = errors.append
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1260
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1261
            entity = cnx.entity_from_eid(action.eid)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1262
        except UnknownEid:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1263
            err(cnx._("can't restore state of entity %s, it has been "
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1264
                      "deleted inbetween") % action.eid)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1265
            return errors
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1266
        self._reedit_entity(entity, action.changes, err)
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1267
        entity.cw_edited.check()
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1268
        self.repo.hm.call_hooks('before_update_entity', cnx, entity=entity)
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
  1269
        sql = self.sqlgen.update(SQL_PREFIX + entity.cw_etype, action.changes,
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1270
                                 ['cw_eid'])
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1271
        self.doexec(cnx, sql, action.changes)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1272
        self.repo.hm.call_hooks('after_update_entity', cnx, entity=entity)
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1273
        return errors
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1274
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1275
    def _undo_a(self, cnx, action):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1276
        """undo a relation addition"""
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1277
        errors = []
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1278
        subj, rtype, obj = action.eid_from, action.rtype, action.eid_to
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1279
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1280
            sentity, oentity, rdef = _undo_rel_info(cnx, subj, rtype, obj)
8695
358d8bed9626 [toward-py3k] rewrite to "except AnException as exc:" (part of #2711624)
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 8694
diff changeset
  1281
        except _UndoException as ex:
10676
9d6b79081bad [py3k] use text/binary types from six
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10662
diff changeset
  1282
            errors.append(text_type(ex))
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1283
        else:
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1284
            rschema = rdef.rtype
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1285
            if rschema.inlined:
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1286
                sql = 'SELECT 1 FROM cw_%s WHERE cw_eid=%s and cw_%s=%s'\
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
  1287
                      % (sentity.cw_etype, subj, rtype, obj)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1288
            else:
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1289
                sql = 'SELECT 1 FROM %s_relation WHERE eid_from=%s and eid_to=%s'\
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1290
                      % (rtype, subj, obj)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1291
            cu = self.doexec(cnx, sql)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1292
            if cu.fetchone() is None:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1293
                errors.append(cnx._(
5098
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1294
                    "Can't undo addition of relation %(rtype)s from %(subj)s to"
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1295
                    " %(obj)s, doesn't exist anymore" % locals()))
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1296
        if not errors:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1297
            self.repo.hm.call_hooks('before_delete_relation', cnx,
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1298
                                    eidfrom=subj, rtype=rtype, eidto=obj)
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1299
            # delete relation from the database
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1300
            self._delete_relation(cnx, subj, rtype, obj, rschema.inlined)
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1301
            # set related cache
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1302
            cnx.update_rel_cache_del(subj, rtype, obj, rschema.symmetric)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1303
            self.repo.hm.call_hooks('after_delete_relation', cnx,
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1304
                                    eidfrom=subj, rtype=rtype, eidto=obj)
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1305
        return errors
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1306
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1307
    # full text index handling #################################################
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1308
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1309
    @cached
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1310
    def need_fti_indexation(self, etype):
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1311
        eschema = self.schema.eschema(etype)
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1312
        if any(eschema.indexable_attributes()):
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1313
            return True
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1314
        if any(eschema.fulltext_containers()):
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1315
            return True
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1316
        return False
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1317
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1318
    def index_entity(self, cnx, entity):
4807
5642bfa43236 [cleanup] add index_entity to abstract source, add docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4806
diff changeset
  1319
        """create an operation to [re]index textual content of the given entity
5642bfa43236 [cleanup] add index_entity to abstract source, add docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4806
diff changeset
  1320
        on commit
5642bfa43236 [cleanup] add index_entity to abstract source, add docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4806
diff changeset
  1321
        """
10631
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
  1322
        if self.do_fti:
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
  1323
            FTIndexEntityOp.get_instance(cnx).add_data(entity.eid)
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1324
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1325
    def fti_unindex_entities(self, cnx, entities):
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1326
        """remove text content for entities from the full text index
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1327
        """
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1328
        cursor = cnx.cnxset.cu
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1329
        cursor_unindex_object = self.dbhelper.cursor_unindex_object
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1330
        try:
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1331
            for entity in entities:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1332
                cursor_unindex_object(entity.eid, cursor)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1333
        except Exception:  # let KeyboardInterrupt / SystemExit propagate
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1334
            self.exception('error while unindexing %s', entity)
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1335
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1336
    def fti_index_entities(self, cnx, entities):
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1337
        """add text content of created/modified entities to the full text index
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1338
        """
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1339
        cursor_index_object = self.dbhelper.cursor_index_object
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1340
        cursor = cnx.cnxset.cu
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1341
        try:
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1342
            # use cursor_index_object, not cursor_reindex_object since
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1343
            # unindexing done in the FTIndexEntityOp
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1344
            for entity in entities:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1345
                cursor_index_object(entity.eid,
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1346
                                    entity.cw_adapt_to('IFTIndexable'),
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1347
                                    cursor)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1348
        except Exception:  # let KeyboardInterrupt / SystemExit propagate
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1349
            self.exception('error while indexing %s', entity)
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1350
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1351
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6366
diff changeset
  1352
class FTIndexEntityOp(hook.DataOperationMixIn, hook.LateOperation):
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1353
    """operation to delay entity full text indexation to commit
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1354
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1355
    since fti indexing may trigger discovery of other entities, it should be
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1356
    triggered on precommit, not commit, and this should be done after other
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1357
    precommit operation which may add relations to the entity
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1358
    """
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1359
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1360
    def precommit_event(self):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1361
        cnx = self.cnx
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1362
        source = cnx.repo.system_source
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1363
        pendingeids = cnx.transaction_data.get('pendingeids', ())
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1364
        done = cnx.transaction_data.setdefault('indexedeids', set())
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1365
        to_reindex = set()
6426
541659c39f6a [hook/operation] nicer api to achieve same result as set_operation, as described in #1253630
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6366
diff changeset
  1366
        for eid in self.get_data():
5070
b1f80ccadda3 [repo] refactor fti operation to use set_operation and a single operation whatever the number of entities to ft index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5067
diff changeset
  1367
            if eid in pendingeids or eid in done:
b1f80ccadda3 [repo] refactor fti operation to use set_operation and a single operation whatever the number of entities to ft index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5067
diff changeset
  1368
                # entity added and deleted in the same transaction or already
b1f80ccadda3 [repo] refactor fti operation to use set_operation and a single operation whatever the number of entities to ft index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5067
diff changeset
  1369
                # processed
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1370
                continue
5070
b1f80ccadda3 [repo] refactor fti operation to use set_operation and a single operation whatever the number of entities to ft index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5067
diff changeset
  1371
            done.add(eid)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1372
            iftindexable = cnx.entity_from_eid(eid).cw_adapt_to('IFTIndexable')
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1373
            to_reindex |= set(iftindexable.fti_containers())
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1374
        source.fti_unindex_entities(cnx, to_reindex)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1375
        source.fti_index_entities(cnx, to_reindex)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1376
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1377
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1378
def sql_schema(driver):
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1379
    """Yield SQL statements to create system tables in the database."""
4831
c5aec27c1bf7 [repo] use logilab.db instead of lgc.adbh/lgc.db/lgc.sqlgen/indexer, test new date extranction functions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4829
diff changeset
  1380
    helper = get_db_helper(driver)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1381
    typemap = helper.TYPE_MAPPING
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1382
    # XXX should return a list of sql statements rather than ';' joined statements
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1383
    for sql in helper.sql_create_numrange('entities_id_seq').split(';'):
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1384
        yield sql
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1385
    for sql in ("""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1386
CREATE TABLE entities (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1387
  eid INTEGER PRIMARY KEY NOT NULL,
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1388
  type VARCHAR(64) NOT NULL,
8205
14c52c5ee706 [entities system table] change asource and source column size (closes #1951819)
Alexandre Richardson <alexandre.richardson@logilab.fr>
parents: 7967
diff changeset
  1389
  asource VARCHAR(128) NOT NULL,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1390
  extid VARCHAR(256)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1391
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1392
CREATE INDEX entities_type_idx ON entities(type);;
10209
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
  1393
CREATE TABLE moved_entities (
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
  1394
  eid INTEGER PRIMARY KEY NOT NULL,
10627
ffef8ac383f4 moved_entities.extid may not be NULL
Julien Cristau <julien.cristau@logilab.fr>
parents: 10626
diff changeset
  1395
  extid VARCHAR(256) UNIQUE NOT NULL
10209
4c64a41c0a1d Use a moved_entities table to record external entities moved to the system source
Julien Cristau <julien.cristau@logilab.fr>
parents: 10208
diff changeset
  1396
);;
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1397
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1398
CREATE TABLE transactions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1399
  tx_uuid CHAR(32) PRIMARY KEY NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1400
  tx_user INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1401
  tx_time %s NOT NULL
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1402
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1403
CREATE INDEX transactions_tx_user_idx ON transactions(tx_user);;
9336
722635e530a0 [server] Add missing indices for undo support (closes #3259691)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9298
diff changeset
  1404
CREATE INDEX transactions_tx_time_idx ON transactions(tx_time);;
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1405
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1406
CREATE TABLE tx_entity_actions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1407
  tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1408
  txa_action CHAR(1) NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1409
  txa_public %s NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1410
  txa_order INTEGER,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1411
  eid INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1412
  etype VARCHAR(64) NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1413
  changes %s
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1414
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1415
CREATE INDEX tx_entity_actions_txa_action_idx ON tx_entity_actions(txa_action);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1416
CREATE INDEX tx_entity_actions_txa_public_idx ON tx_entity_actions(txa_public);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1417
CREATE INDEX tx_entity_actions_eid_idx ON tx_entity_actions(eid);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1418
CREATE INDEX tx_entity_actions_etype_idx ON tx_entity_actions(etype);;
9336
722635e530a0 [server] Add missing indices for undo support (closes #3259691)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9298
diff changeset
  1419
CREATE INDEX tx_entity_actions_tx_uuid_idx ON tx_entity_actions(tx_uuid);;
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1420
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1421
CREATE TABLE tx_relation_actions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1422
  tx_uuid CHAR(32) REFERENCES transactions(tx_uuid) ON DELETE CASCADE,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1423
  txa_action CHAR(1) NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1424
  txa_public %s NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1425
  txa_order INTEGER,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1426
  eid_from INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1427
  eid_to INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1428
  rtype VARCHAR(256) NOT NULL
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1429
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1430
CREATE INDEX tx_relation_actions_txa_action_idx ON tx_relation_actions(txa_action);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1431
CREATE INDEX tx_relation_actions_txa_public_idx ON tx_relation_actions(txa_public);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1432
CREATE INDEX tx_relation_actions_eid_from_idx ON tx_relation_actions(eid_from);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1433
CREATE INDEX tx_relation_actions_eid_to_idx ON tx_relation_actions(eid_to);;
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1434
CREATE INDEX tx_relation_actions_tx_uuid_idx ON tx_relation_actions(tx_uuid)
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1435
""" % (typemap['Datetime'],
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1436
       typemap['Boolean'], typemap['Bytes'], typemap['Boolean'])).split(';'):
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1437
        yield sql
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1438
    if helper.backend_name == 'sqlite':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1439
        # sqlite support the ON DELETE CASCADE syntax but do nothing
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1440
        yield '''
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1441
CREATE TRIGGER fkd_transactions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1442
BEFORE DELETE ON transactions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1443
FOR EACH ROW BEGIN
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1444
    DELETE FROM tx_entity_actions WHERE tx_uuid=OLD.tx_uuid;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1445
    DELETE FROM tx_relation_actions WHERE tx_uuid=OLD.tx_uuid;
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1446
END;
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1447
'''
11087
35b29f1eb37a drop a note about usage of sqls_create_multicol_unique_index and avoid a lgdb warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
  1448
    # define a multi-columns index on a single index to please sqlserver, which doesn't like several
35b29f1eb37a drop a note about usage of sqls_create_multicol_unique_index and avoid a lgdb warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11057
diff changeset
  1449
    # null entries in a UNIQUE column
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1450
    for sql in helper.sqls_create_multicol_unique_index('entities', ['extid'],
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1451
                                                        'entities_extid_idx'):
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1452
        yield sql
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1453
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1454
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1455
def grant_schema(user, set_owner=True):
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1456
    """Yield SQL statements to give all access (and ownership if `set_owner` is True) on the
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1457
    database system tables to `user`.
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1458
    """
9450
af4b93bc38a5 [multi-sources-removal] Drop deleted_entities system table and entities.mtime column
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 9448
diff changeset
  1459
    for table in ('entities', 'entities_id_seq',
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1460
                  'transactions', 'tx_entity_actions', 'tx_relation_actions'):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1461
        if set_owner:
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1462
            yield 'ALTER TABLE %s OWNER TO %s;' % (table, user)
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1463
        yield 'GRANT ALL ON %s TO %s;' % (table, user)
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1464
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1465
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1466
class BaseAuthentifier(object):
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1467
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1468
    def __init__(self, source=None):
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1469
        self.source = source
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1470
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1471
    def set_schema(self, schema):
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1472
        """set the instance'schema"""
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1473
        pass
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1474
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1475
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1476
class LoginPasswordAuthentifier(BaseAuthentifier):
8520
fcd048fa6e6d [source/native] only system source users should be authenticated by the native source (closes #2465883)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8508
diff changeset
  1477
    passwd_rql = 'Any P WHERE X is CWUser, X login %(login)s, X upassword P'
10095
200bd6a601dc [warnings] put an end to warnings in the sqlite driver over `str` being sent instead of unicode strings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10086
diff changeset
  1478
    auth_rql = (u'Any X WHERE X is CWUser, X login %(login)s, X upassword %(pwd)s, '
8520
fcd048fa6e6d [source/native] only system source users should be authenticated by the native source (closes #2465883)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8508
diff changeset
  1479
                'X cw_source S, S name "system"')
fcd048fa6e6d [source/native] only system source users should be authenticated by the native source (closes #2465883)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 8508
diff changeset
  1480
    _sols = ({'X': 'CWUser', 'P': 'Password', 'S': 'CWSource'},)
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1481
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1482
    def set_schema(self, schema):
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1483
        """set the instance'schema"""
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1484
        if 'CWUser' in schema:  # probably an empty schema if not true...
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1485
            # rql syntax trees used to authenticate users
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1486
            self._passwd_rqlst = self.source.compile_rql(self.passwd_rql, self._sols)
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1487
            self._auth_rqlst = self.source.compile_rql(self.auth_rql, self._sols)
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1488
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1489
    def authenticate(self, cnx, login, password=None, **kwargs):
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1490
        """return CWUser eid for the given login/password if this account is
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1491
        defined in this source, else raise `AuthenticationError`
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1492
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1493
        two queries are needed since passwords are stored crypted, so we have
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1494
        to fetch the salt first
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1495
        """
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1496
        args = {'login': login, 'pwd': None}
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1497
        if password is not None:
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1498
            rset = self.source.syntax_tree_search(cnx, self._passwd_rqlst, args)
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1499
            try:
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1500
                pwd = rset[0][0]
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1501
            except IndexError:
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1502
                raise AuthenticationError('bad login')
8235
c2a91d6639d8 [system source] fix authentication: don't allow login whatever the given password if user password is NULL in database. Closes #2186099
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8205
diff changeset
  1503
            if pwd is None:
c2a91d6639d8 [system source] fix authentication: don't allow login whatever the given password if user password is NULL in database. Closes #2186099
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8205
diff changeset
  1504
                # if pwd is None but a password is provided, something is wrong
c2a91d6639d8 [system source] fix authentication: don't allow login whatever the given password if user password is NULL in database. Closes #2186099
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8205
diff changeset
  1505
                raise AuthenticationError('bad password')
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1506
            # passwords are stored using the Bytes type, so we get a StringIO
8317
9c59258e7798 [security] use a stronger encryption algorythm for password, keeping bw compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8235
diff changeset
  1507
            args['pwd'] = Binary(crypt_password(password, pwd.getvalue()))
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1508
        # get eid from login and (crypted) password
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1509
        rset = self.source.syntax_tree_search(cnx, self._auth_rqlst, args)
10037
6b83ceda8323 [server] fix LoginPasswordAuthentifier.authenticate
David Douard <david.douard@logilab.fr>
parents: 9996
diff changeset
  1510
        pwd = args['pwd']
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1511
        try:
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1512
            user = rset[0][0]
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1513
            # If the stored hash uses a deprecated scheme (e.g. DES or MD5 used
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1514
            # before 3.14.7), update with a fresh one
10037
6b83ceda8323 [server] fix LoginPasswordAuthentifier.authenticate
David Douard <david.douard@logilab.fr>
parents: 9996
diff changeset
  1515
            if pwd is not None and pwd.getvalue():
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1516
                verify, newhash = verify_and_update(password, pwd.getvalue())
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1517
                if not verify:  # should not happen, but...
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1518
                    raise AuthenticationError('bad password')
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1519
                if newhash:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1520
                    cnx.system_sql("UPDATE %s SET %s=%%(newhash)s WHERE %s=%%(login)s"
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1521
                                   % (SQL_PREFIX + 'CWUser',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1522
                                      SQL_PREFIX + 'upassword',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1523
                                      SQL_PREFIX + 'login'),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1524
                                   {'newhash': self.source._binary(newhash.encode('ascii')),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1525
                                    'login': login})
10364
8b35a898b334 [server] remove cnxset tracking, it is now unneeded
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10360
diff changeset
  1526
                    cnx.commit()
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1527
            return user
3647
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1528
        except IndexError:
2941f4a0aab9 refactor repo authentication to allow pluggable authentifier to login with something else than a password
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3503
diff changeset
  1529
            raise AuthenticationError('bad password')
6849
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1530
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1531
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1532
class EmailPasswordAuthentifier(BaseAuthentifier):
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1533
    def authenticate(self, cnx, login, **authinfo):
6849
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1534
        # email_auth flag prevent from infinite recursion (call to
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1535
        # repo.check_auth_info at the end of this method may lead us here again)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1536
        if '@' not in login or authinfo.pop('email_auth', None):
6849
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1537
            raise AuthenticationError('not an email')
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1538
        rset = cnx.execute('Any L WHERE U login L, U primary_email M, '
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1539
                           'M address %(login)s', {'login': login},
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1540
                           build_descr=False)
6849
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1541
        if rset.rowcount != 1:
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1542
            raise AuthenticationError('unexisting email')
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1543
        login = rset.rows[0][0]
5a0c2cfc19bf [repository auth] cleanup email login by turning it into a proper repo-side authentication plugin
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6724
diff changeset
  1544
        authinfo['email_auth'] = True
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1545
        return self.source.repo.check_auth_info(cnx, login, authinfo)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1546
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1547
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1548
class DatabaseIndependentBackupRestore(object):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1549
    """Helper class to perform db backend agnostic backup and restore
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1550
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1551
    The backup and restore methods are used to dump / restore the
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1552
    system database in a database independent format. The file is a
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1553
    Zip archive containing the following files:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1554
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1555
    * format.txt: the format of the archive. Currently '1.1'
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1556
    * tables.txt: list of filenames in the archive tables/ directory
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1557
    * sequences.txt: list of filenames in the archive sequences/ directory
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1558
    * numranges.txt: list of filenames in the archive numrange/ directory
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1559
    * versions.txt: the list of cube versions from CWProperty
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1560
    * tables/<tablename>.<chunkno>: pickled data
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1561
    * sequences/<sequencename>: pickled data
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1562
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1563
    The pickled data format for tables, numranges and sequences is a tuple of 3 elements:
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1564
    * the table name
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1565
    * a tuple of column names
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1566
    * a list of rows (as tuples with one element per column)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1567
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1568
    Tables are saved in chunks in different files in order to prevent
7551
2d4ba5b984dc cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7530
diff changeset
  1569
    a too high memory consumption.
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1570
    """
10048
7d9256aab337 [source/native/backup_restore] have a unique tunable blocksize for the dump phase
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
  1571
    blocksize = 100
7d9256aab337 [source/native/backup_restore] have a unique tunable blocksize for the dump phase
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
  1572
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1573
    def __init__(self, source):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1574
        """
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1575
        :param: source an instance of the system source
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1576
        """
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1577
        self._source = source
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1578
        self.logger = logging.getLogger('cubicweb.ctl')
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1579
        self.logger.setLevel(logging.INFO)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1580
        self.logger.addHandler(logging.StreamHandler(sys.stdout))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1581
        self.schema = self._source.schema
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1582
        self.dbhelper = self._source.dbhelper
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1583
        self.cnx = None
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1584
        self.cursor = None
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1585
        self.sql_generator = sqlgen.SQLGenerator()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1586
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1587
    def get_connection(self):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1588
        return self._source.get_connection()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1589
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1590
    def backup(self, backupfile):
8910
7652c3d46ba3 [portable dump] skip virtual relations, they have no table associated. Closes #2841199
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8821
diff changeset
  1591
        archive = zipfile.ZipFile(backupfile, 'w', allowZip64=True)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1592
        self.cnx = self.get_connection()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1593
        try:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1594
            self.cursor = self.cnx.cursor()
9468
39b7a91a3f4c [repo] pylint cleanup, mainly of imports, with a bit of style
Julien Cristau <julien.cristau@logilab.fr>
parents: 9467
diff changeset
  1595
            self.cursor.arraysize = 100
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1596
            self.logger.info('writing metadata')
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1597
            self.write_metadata(archive)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1598
            for seq in self.get_sequences():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1599
                self.logger.info('processing sequence %s', seq)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1600
                self.write_sequence(archive, seq)
10196
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1601
            for numrange in self.get_numranges():
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1602
                self.logger.info('processing numrange %s', numrange)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1603
                self.write_numrange(archive, numrange)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1604
            for table in self.get_tables():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1605
                self.logger.info('processing table %s', table)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1606
                self.write_table(archive, table)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1607
        finally:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1608
            archive.close()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1609
            self.cnx.close()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1610
        self.logger.info('done')
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1611
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1612
    def get_tables(self):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1613
        non_entity_tables = ['entities',
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1614
                             'transactions',
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1615
                             'tx_entity_actions',
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1616
                             'tx_relation_actions',
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1617
                             ]
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1618
        etype_tables = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1619
        relation_tables = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1620
        prefix = 'cw_'
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1621
        for etype in self.schema.entities():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1622
            eschema = self.schema.eschema(etype)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1623
            if eschema.final:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1624
                continue
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1625
            etype_tables.append('%s%s' % (prefix, etype))
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1626
        for rtype in self.schema.relations():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1627
            rschema = self.schema.rschema(rtype)
8910
7652c3d46ba3 [portable dump] skip virtual relations, they have no table associated. Closes #2841199
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8821
diff changeset
  1628
            if rschema.final or rschema.inlined or rschema in VIRTUAL_RTYPES:
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1629
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1630
            relation_tables.append('%s_relation' % rtype)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1631
        return non_entity_tables + etype_tables + relation_tables
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1632
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1633
    def get_sequences(self):
10196
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1634
        return []
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1635
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1636
    def get_numranges(self):
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1637
        return ['entities_id_seq']
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1638
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1639
    def write_metadata(self, archive):
10196
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1640
        archive.writestr('format.txt', '1.1')
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1641
        archive.writestr('tables.txt', '\n'.join(self.get_tables()))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1642
        archive.writestr('sequences.txt', '\n'.join(self.get_sequences()))
10196
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1643
        archive.writestr('numranges.txt', '\n'.join(self.get_numranges()))
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1644
        versions = self._get_versions()
9468
39b7a91a3f4c [repo] pylint cleanup, mainly of imports, with a bit of style
Julien Cristau <julien.cristau@logilab.fr>
parents: 9467
diff changeset
  1645
        versions_str = '\n'.join('%s %s' % (k, v)
39b7a91a3f4c [repo] pylint cleanup, mainly of imports, with a bit of style
Julien Cristau <julien.cristau@logilab.fr>
parents: 9467
diff changeset
  1646
                                 for k, v in versions)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1647
        archive.writestr('versions.txt', versions_str)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1648
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1649
    def write_sequence(self, archive, seq):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1650
        sql = self.dbhelper.sql_sequence_current_state(seq)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1651
        columns, rows_iterator = self._get_cols_and_rows(sql)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1652
        rows = list(rows_iterator)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1653
        serialized = self._serialize(seq, columns, rows)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1654
        archive.writestr('sequences/%s' % seq, serialized)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1655
10196
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1656
    def write_numrange(self, archive, numrange):
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1657
        sql = self.dbhelper.sql_numrange_current_state(numrange)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1658
        columns, rows_iterator = self._get_cols_and_rows(sql)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1659
        rows = list(rows_iterator)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1660
        serialized = self._serialize(numrange, columns, rows)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1661
        archive.writestr('numrange/%s' % numrange, serialized)
20d56b1f035e [backup/portable] properly write the eid numrange generator (the eid is no more a sequence)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10183
diff changeset
  1662
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1663
    def write_table(self, archive, table):
7753
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1664
        nb_lines_sql = 'SELECT COUNT(*) FROM %s' % table
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1665
        self.cursor.execute(nb_lines_sql)
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1666
        rowcount = self.cursor.fetchone()[0]
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1667
        sql = 'SELECT * FROM %s' % table
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1668
        columns, rows_iterator = self._get_cols_and_rows(sql)
7753
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1669
        self.logger.info('number of rows: %d', rowcount)
10048
7d9256aab337 [source/native/backup_restore] have a unique tunable blocksize for the dump phase
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
  1670
        blocksize = self.blocksize
7753
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1671
        if rowcount > 0:
10609
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10602
diff changeset
  1672
            for i, start in enumerate(range(0, rowcount, blocksize)):
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1673
                rows = list(itertools.islice(rows_iterator, blocksize))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1674
                serialized = self._serialize(table, columns, rows)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1675
                archive.writestr('tables/%s.%04d' % (table, i), serialized)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1676
                self.logger.debug('wrote rows %d to %d (out of %d) to %s.%04d',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1677
                                  start, start + len(rows) - 1,
7753
681ef2a664dd work around cursor.rowcount not returning anything useful before 1st fetch with mssql (closes #1910869)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 7551
diff changeset
  1678
                                  rowcount,
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1679
                                  table, i)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1680
        else:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1681
            rows = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1682
            serialized = self._serialize(table, columns, rows)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1683
            archive.writestr('tables/%s.%04d' % (table, 0), serialized)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1684
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1685
    def _get_cols_and_rows(self, sql):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1686
        process_result = self._source.iter_process_result
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1687
        self.cursor.execute(sql)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1688
        columns = (d[0] for d in self.cursor.description)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1689
        rows = process_result(self.cursor)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1690
        return tuple(columns), rows
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1691
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1692
    def _serialize(self, name, columns, rows):
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1693
        return pickle.dumps((name, columns, rows), pickle.HIGHEST_PROTOCOL)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1694
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1695
    def restore(self, backupfile):
7787
d9607ae447d2 [server] portable dump format supports now ZIP64 extensions by default (closes #1912535)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7786
diff changeset
  1696
        archive = zipfile.ZipFile(backupfile, 'r', allowZip64=True)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1697
        self.cnx = self.get_connection()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1698
        self.cursor = self.cnx.cursor()
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1699
        sequences, numranges, tables, table_chunks = self.read_metadata(archive, backupfile)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1700
        for seq in sequences:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1701
            self.logger.info('restoring sequence %s', seq)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1702
            self.read_sequence(archive, seq)
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1703
        for numrange in numranges:
10623
b9322cc17d7e [sources/native] fix potential NameError (closes #7364249)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10270
diff changeset
  1704
            self.logger.info('restoring numrange %s', numrange)
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1705
            self.read_numrange(archive, numrange)
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1706
        for table in tables:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1707
            self.logger.info('restoring table %s', table)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1708
            self.read_table(archive, table, sorted(table_chunks[table]))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1709
        self.cnx.close()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1710
        archive.close()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1711
        self.logger.info('done')
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1712
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1713
    def read_metadata(self, archive, backupfile):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1714
        formatinfo = archive.read('format.txt')
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1715
        self.logger.info('checking metadata')
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1716
        if formatinfo.strip() != "1.1":
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1717
            self.logger.critical('Unsupported format in archive: %s', formatinfo)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1718
            raise ValueError('Unknown format in %s: %s' % (backupfile, formatinfo))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1719
        tables = archive.read('tables.txt').splitlines()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1720
        sequences = archive.read('sequences.txt').splitlines()
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1721
        numranges = archive.read('numranges.txt').splitlines()
11060
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1722
        archive_versions = self._parse_versions(archive.read('versions.txt'))
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1723
        db_versions = set(self._get_versions())
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1724
        if archive_versions != db_versions:
11115
a385bd146178 [sources/native] remove extra space before colon
Julien Cristau <julien.cristau@logilab.fr>
parents: 11060
diff changeset
  1725
            self.logger.critical('Restore warning: versions do not match')
11060
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1726
            new_cubes = db_versions - archive_versions
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1727
            if new_cubes:
11115
a385bd146178 [sources/native] remove extra space before colon
Julien Cristau <julien.cristau@logilab.fr>
parents: 11060
diff changeset
  1728
                self.logger.critical('In the db:\n%s', '\n'.join('%s: %s' % (cube, ver)
11060
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1729
                                                            for cube, ver in sorted(new_cubes)))
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1730
            old_cubes = archive_versions - db_versions
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1731
            if old_cubes:
11115
a385bd146178 [sources/native] remove extra space before colon
Julien Cristau <julien.cristau@logilab.fr>
parents: 11060
diff changeset
  1732
                self.logger.critical('In the archive:\n%s', '\n'.join('%s: %s' % (cube, ver)
11060
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1733
                                                            for cube, ver in sorted(old_cubes)))
3699fca78836 [sources/native] ask permission to continue restoring even if metadata do not match (closes #7771864)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10623
diff changeset
  1734
            if not ASK.confirm('Versions mismatch: continue anyway ?', False):
11115
a385bd146178 [sources/native] remove extra space before colon
Julien Cristau <julien.cristau@logilab.fr>
parents: 11060
diff changeset
  1735
                raise ValueError('Unable to restore: versions do not match')
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1736
        table_chunks = {}
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1737
        for name in archive.namelist():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1738
            if not name.startswith('tables/'):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1739
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1740
            filename = basename(name)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1741
            tablename, _ext = filename.rsplit('.', 1)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1742
            table_chunks.setdefault(tablename, []).append(name)
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1743
        return sequences, numranges, tables, table_chunks
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1744
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1745
    def read_sequence(self, archive, seq):
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1746
        seqname, columns, rows = pickle.loads(archive.read('sequences/%s' % seq))
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1747
        assert seqname == seq
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1748
        assert len(rows) == 1
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1749
        assert len(rows[0]) == 1
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1750
        value = rows[0][0]
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1751
        sql = self.dbhelper.sql_restart_sequence(seq, value)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1752
        self.cursor.execute(sql)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1753
        self.cnx.commit()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1754
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1755
    def read_numrange(self, archive, numrange):
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1756
        rangename, columns, rows = pickle.loads(archive.read('numrange/%s' % numrange))
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1757
        assert rangename == numrange
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1758
        assert len(rows) == 1
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1759
        assert len(rows[0]) == 1
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1760
        value = rows[0][0]
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1761
        sql = self.dbhelper.sql_restart_numrange(numrange, value)
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1762
        self.cursor.execute(sql)
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1763
        self.cnx.commit()
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1764
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1765
    def read_table(self, archive, table, filenames):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1766
        merge_args = self._source.merge_args
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1767
        self.cursor.execute('DELETE FROM %s' % table)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1768
        self.cnx.commit()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1769
        row_count = 0
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1770
        for filename in filenames:
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1771
            tablename, columns, rows = pickle.loads(archive.read(filename))
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1772
            assert tablename == table
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1773
            if not rows:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1774
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1775
            insert = self.sql_generator.insert(table,
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1776
                                               dict(zip(columns, rows[0])))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1777
            for row in rows:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1778
                self.cursor.execute(insert, merge_args(dict(zip(columns, row)), {}))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1779
            row_count += len(rows)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1780
            self.cnx.commit()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1781
        self.logger.info('inserted %d rows', row_count)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1782
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1783
    def _parse_versions(self, version_str):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1784
        versions = set()
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1785
        for line in version_str.splitlines():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1786
            versions.add(tuple(line.split()))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1787
        return versions
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1788
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1789
    def _get_versions(self):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1790
        version_sql = 'SELECT cw_pkey, cw_value FROM cw_CWProperty'
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1791
        versions = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1792
        self.cursor.execute(version_sql)
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1793
        for pkey, value in self.cursor.fetchall():
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1794
            if pkey.startswith(u'system.version'):
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1795
                versions.append((pkey, value))
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1796
        return versions