cubicweb/server/sources/native.py
author Laurent Peuch <cortex@worlddomination.be>
Thu, 01 Aug 2019 05:42:45 +0200
changeset 12756 d91c229de97f
parent 12739 c6f8ca03718f
child 12758 db95a417a5ec
permissions -rw-r--r--
[debug/rql] bind a uniq token per rql to trace its decomposition This is aimed to be used by the RQL debug panel (and the SQL one later on) but can also be used by other debugging tools.
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/>.
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
    18
"""Adapters for native cubicweb sources."""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    19
4900
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4893
diff changeset
    20
from threading import Lock
1016
26387b836099 use datetime instead of mx.DateTime
sylvain.thenault@logilab.fr
parents: 973
diff changeset
    21
from datetime import datetime
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
    22
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
    23
from os.path import basename
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
    24
import pickle
6211
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
    25
import re
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
    26
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
    27
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
    28
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
    29
import sys
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
    31
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
    32
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
    33
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
    34
from logilab.database import get_db_helper, sqlgen
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
    36
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
    37
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
    38
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
    39
                      UniqueTogetherError, UndoTransactionException, ViolatedConstraint)
12149
649100470733 [sources] Stop translating validation error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12148
diff changeset
    40
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
    41
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
    42
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
    43
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
    44
from cubicweb.server import hook
10200
cceb2c7c02f4 Use our version of schema2sql
Julien Cristau <julien.cristau@logilab.fr>
parents: 10187
diff changeset
    45
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
    46
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
    47
from cubicweb.server.sqlutils import SQL_PREFIX, SQLAdapterMixIn
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    48
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
    49
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
    50
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
    51
from cubicweb.server.sources import AbstractSource, dbg_st_search, dbg_results
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    52
from cubicweb.server.sources.rql2sql import SQLGenerator
12739
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
    53
from cubicweb.misc.source_highlight import highlight
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
    54
from cubicweb.statsd_logger import statsd_timeit
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    55
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    56
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
    57
ATTR_MAP = {}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    58
NONSYSTEM_ETYPES = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    59
NONSYSTEM_RELATIONS = set()
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    60
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
    61
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    62
class LogCursor(object):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    63
    def __init__(self, cursor):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    64
        self.cu = cursor
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    65
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    66
    def execute(self, query, args=None):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    67
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    68
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    69
        """
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
    70
        if server.DEBUG & server.DBG_SQL:
12739
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
    71
            print('exec', highlight(query, "SQL"), args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    72
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    73
            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
    74
        except Exception as ex:
10589
7c23b7de2b8d [py3k] print function
Samuel Trégouët <samuel.tregouet@logilab.fr>
parents: 10580
diff changeset
    75
            print("sql: %r\n args: %s\ndbms message: %r" % (
12739
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
    76
                highlight(query, "SQL"), args, ex.args[0]))
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    77
            raise
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    78
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    79
    def fetchall(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    80
        return self.cu.fetchall()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    81
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    82
    def fetchone(self):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    83
        return self.cu.fetchone()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    84
2625
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
    85
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    86
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
    87
    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
    88
    restrclauses = restr.split(' AND ')
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    89
    for clause in clauses:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    90
        restrclauses.remove(clause)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    91
    if restrclauses:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    92
        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
    93
                                 ' OR '.join(clauses))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    94
    else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    95
        restr = '(%s)' % ' OR '.join(clauses)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
    96
    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
    97
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
    98
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
    99
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
   100
    """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
   101
    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
   102
    """
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
   103
    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
   104
            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
   105
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
   106
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
   107
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
   108
    """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
   109
    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
   110
    """
11005
f8417bd135ed [server, hooks] allow callable in dbh.TYPE_MAPPING
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10915
diff changeset
   111
    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
   112
        return dbhelper.TYPE_MAPPING['Int']
11359
2da2dd60331c [sql gen] Explicitly name unique index
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11351
diff changeset
   113
    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
   114
    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
   115
    return coltype, allownull
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   116
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   117
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   118
class _UndoException(Exception):
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   119
    """something went wrong during undoing"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   120
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   121
    def __str__(self):
7530
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   122
        """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
   123
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   124
        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
   125
        """
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
   126
        return self.args[0]
7530
15178bf89fb6 [server] fix unicode conversion capability in UndoException
Julien Jehannet <julien.jehannet@logilab.fr>
parents: 7507
diff changeset
   127
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   128
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   129
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
   130
    """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
   131
    card = rdef.role_cardinality(role)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   132
    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
   133
        msg = tentity._cw._(
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   134
            "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
   135
            "is already linked using this relation.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   136
        raise _UndoException(msg % {'role': neg_role(role),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   137
                                    'rtype': rdef.rtype,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   138
                                    'eid': tentity.eid})
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   139
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   140
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   141
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
   142
    entities = []
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
   143
    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
   144
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   145
            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
   146
        except UnknownEid:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   147
            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
   148
                "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
   149
                " doesn't exist anymore.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   150
            raise _UndoException(msg % {'role': cnx._(role),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   151
                                        'rtype': cnx._(rtype),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   152
                                        '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
   153
    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
   154
    try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   155
        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
   156
        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
   157
    except KeyError:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   158
        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
   159
            "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
   160
            "%(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
   161
            "schema.")
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   162
        raise _UndoException(msg % {'rtype': cnx._(rtype),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   163
                                    'subj': subj,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   164
                                    '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
   165
    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
   166
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   167
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   168
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
   169
    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
   170
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
   171
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
   172
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
   173
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
   174
            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
   175
     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
   176
               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
   177
                   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
   178
     )''' % {'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
   179
             '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
   180
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   181
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   182
class DefaultEidGenerator(object):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   183
    __slots__ = ('source', 'cnx', 'lock')
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   184
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   185
    def __init__(self, source):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   186
        self.source = source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   187
        self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   188
        self.lock = Lock()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   189
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   190
    def close(self):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   191
        if self.cnx:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   192
            self.cnx.close()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   193
        self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   194
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   195
    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
   196
        # 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
   197
        # 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
   198
        assert count > 0
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   199
        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
   200
            return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   201
9585
3f5b59527d31 [source/native] allow many eid creation per .create_eid call (closes #3526594)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9583
diff changeset
   202
    def _create_eid(self, count):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   203
        # 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
   204
        # 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
   205
        # deadlock on self._eid_cnx_lock
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   206
        source = self.source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   207
        if self.cnx is None:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   208
            self.cnx = source.get_connection()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   209
        cnx = self.cnx
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   210
        try:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   211
            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
   212
            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
   213
                cursor.execute(sql)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   214
            eid = cursor.fetchone()[0]
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   215
        except (source.OperationalError, source.InterfaceError):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   216
            # FIXME: better detection of deconnection pb
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   217
            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
   218
            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
   219
            return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   220
        except source.DbapiError as exc:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   221
            # 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
   222
            if exc.args[0] == '08S01':
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   223
                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
   224
                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
   225
                return self._create_eid(count)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   226
            else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   227
                raise
12156
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
   228
        except Exception:  # WTF?
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   229
            cnx.rollback()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   230
            self.cnx = None
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   231
            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
   232
            raise
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   233
        else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   234
            cnx.commit()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   235
            return eid
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   236
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   237
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   238
class SQLITEEidGenerator(object):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   239
    __slots__ = ('source', 'lock')
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   240
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   241
    def __init__(self, source):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   242
        self.source = source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   243
        self.lock = Lock()
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   244
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   245
    def close(self):
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   246
        pass
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   247
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   248
    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
   249
        assert count > 0
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   250
        source = self.source
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   251
        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
   252
            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
   253
                cursor = source.doexec(cnx, sql)
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   254
            return cursor.fetchone()[0]
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   255
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   256
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   257
class NativeSQLSource(SQLAdapterMixIn, AbstractSource):
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   258
    """adapter for source using the native cubicweb schema (see below)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   259
    """
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
   260
    sqlgen_class = SQLGenerator
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   261
    options = (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   262
        ('db-driver',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   263
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   264
          '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
   265
          # 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
   266
          '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
   267
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   268
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   269
        ('db-host',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   270
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   271
          'default': '',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   272
          '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
   273
          'group': 'native-source', 'level': 1,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   274
          }),
2566
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   275
        ('db-port',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   276
         {'type': 'string',
2566
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   277
          'default': '',
714a8743d423 missing db-port option to source's option definitions
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   278
          '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
   279
          '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
   280
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   281
        ('db-name',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   282
         {'type': 'string',
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   283
          'default': Method('default_instance_id'),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   284
          '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
   285
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   286
          }),
10125
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   287
        ('db-namespace',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   288
         {'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
   289
          'default': '',
bc6461a7d2da [server] add a db-namespace option in source definition (closes #1631339)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 10095
diff changeset
   290
          '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
   291
          '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
   292
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   293
        ('db-user',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   294
         {'type': 'string',
3835
a191b3b9e455 more sensible default values to c-c "create" inputs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3689
diff changeset
   295
          'default': CubicWebNoAppConfiguration.mode == 'user' and getlogin() or 'cubicweb',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   296
          '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
   297
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   298
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   299
        ('db-password',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   300
         {'type': 'password',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   301
          'default': '',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   302
          '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
   303
          'group': 'native-source', 'level': 0,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   304
          }),
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   305
        ('db-encoding',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   306
         {'type': 'string',
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   307
          'default': 'utf8',
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   308
          '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
   309
          'group': 'native-source', 'level': 1,
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   310
          }),
5413
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   311
        ('db-extra-arguments',
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   312
         {'type': 'string',
5413
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   313
          'default': '',
dc896e698ab0 added db-extra-arguments to configuration parameters for native source
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 5410
diff changeset
   314
          '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
   315
                  '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
   316
          '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
   317
          }),
9724
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   318
        ('db-statement-timeout',
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   319
         {'type': 'int',
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   320
          'default': 0,
e45bf9baa7b7 Add a db-statement-timeout option for postgresql sources
Julien Cristau <julien.cristau@logilab.fr>
parents: 9664
diff changeset
   321
          '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
   322
          '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
   323
          }),
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   324
    )
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   325
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   326
    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
   327
        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
   328
        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
   329
        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
   330
            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
   331
        AbstractSource.__init__(self, repo, source_config, *args, **kwargs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   332
        # sql generator
6427
c8a5ac2d1eaa [schema / sources] store data sources as cubicweb entities
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6426
diff changeset
   333
        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
   334
                                             ATTR_MAP.copy())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   335
        # 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
   336
        self.do_fti = not repo.config['delay-full-text-indexation']
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   337
        # 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
   338
        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
   339
        # (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
   340
        self._storages = {}
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   341
        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
   342
        if self.dbdriver == 'sqlite':
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   343
            self.eid_generator = SQLITEEidGenerator(self)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   344
        else:
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   345
            self.eid_generator = DefaultEidGenerator(self)
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   346
        self.create_eid = self.eid_generator.create_eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   347
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   348
    def check_config(self, source_entity):
12152
f34d18d0603f [sources] Check sources configuration is fine on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12149
diff changeset
   349
        if source_entity.config:
f34d18d0603f [sources] Check sources configuration is fine on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12149
diff changeset
   350
            msg = _("Configuration of the system source goes to "
f34d18d0603f [sources] Check sources configuration is fine on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12149
diff changeset
   351
                    "the 'sources' file, not in the database")
6945
28bf94d062a9 [sources] refactor source creation and options handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6931
diff changeset
   352
            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
   353
12153
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   354
    def check_urls(self, source_entity):
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   355
        if source_entity.url:
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   356
            msg = _("Configuration of the system source goes to "
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   357
                    "the 'sources' file, not in the database")
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   358
            raise ValidationError(source_entity.eid, {role_name('config', 'subject'): msg})
0ff0aff4413d [sources] Check source's url attribute value on creation/modification
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12152
diff changeset
   359
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
   360
    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
   361
        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
   362
        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
   363
        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
   364
12061
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   365
    def clear_caches(self, eids, etypes):
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   366
        """Clear potential source caches."""
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   367
        if eids is None:
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   368
            self._cache = QueryCache(self.repo.config['rql-cache-size'])
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   369
        else:
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   370
            cache = self._cache
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   371
            for eid, etype in zip(eids, etypes):
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   372
                cache.pop('Any X WHERE X eid %s' % eid, None)
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   373
                cache.pop('Any %s' % eid, None)
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   374
                if etype is not None:
94ae25593c38 [repo] Consistent API for cache clearing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11979
diff changeset
   375
                    cache.pop('Any X WHERE X eid %s, X is %s' % (eid, etype), None)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   376
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   377
    @statsd_timeit
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   378
    def sqlexec(self, cnx, sql, args=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   379
        """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
   380
        return self.process_result(self.doexec(cnx, sql, args))
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   381
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
   382
    def init_creating(self, cnxset=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   383
        # 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
   384
        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
   385
            if cnxset is None:
11931
ad7796dabeaa [repository] move cnxset pool handling to a helper class
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11926
diff changeset
   386
                _cnxset = self.repo.cnxsets.get()
6724
24bf6f181d0e [pyro source] store pyro source mapping file into the database
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6427
diff changeset
   387
            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
   388
                _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
   389
            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
   390
                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
   391
                    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
   392
                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
   393
            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
   394
                _cnxset.cnxset_freed()
11931
ad7796dabeaa [repository] move cnxset pool handling to a helper class
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11926
diff changeset
   395
                self.repo.cnxsets.release(_cnxset)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   396
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   397
    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
   398
        """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
   399
        if format == 'portable':
8947
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   400
            # 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
   401
            # 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
   402
            # so force reload
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   403
            if self.repo.config.quick_start:
3bbd416b09ec [repo] straightforward bootstrap sequence. Closes #2841188
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 8916
diff changeset
   404
                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
   405
                                     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
   406
            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
   407
            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
   408
            try:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   409
                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
   410
            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
   411
                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
   412
        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
   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
                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
   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
        else:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   419
            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
   420
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
   421
    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
   422
        """method called to restore a backup of source's data"""
11979
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   423
        if format == 'portable':
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   424
            helper = DatabaseIndependentBackupRestore(self)
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   425
            helper.restore(backupfile)
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   426
        elif format == 'native':
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   427
            self.restore_from_file(backupfile, confirm, drop=drop)
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   428
        else:
c93b47ba0093 [server] Drop close/open steps in NativeSQLSource.restore()
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11931
diff changeset
   429
            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
   430
12148
79160d54662e [sources] Simplify source's init method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12061
diff changeset
   431
    def init(self, source_entity):
79160d54662e [sources] Simplify source's init method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12061
diff changeset
   432
        super(NativeSQLSource, self).init(source_entity)
9131
b3ad80aa645f fix migration from pre-3.13.1 versions (closes #2846978)
Julien Cristau <julien.cristau@logilab.fr>
parents: 9130
diff changeset
   433
        self.init_creating(source_entity._cw.cnxset)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   434
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
   435
    def shutdown(self):
9583
e337a9f658e0 [source/native] refactor eid generation code
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9574
diff changeset
   436
        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
   437
9492
c7fc56eecd1a English typography
Dimitri Papadopoulos <dimitri.papadopoulos@cea.fr>
parents: 9375
diff changeset
   438
    # 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
   439
    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
   440
        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
   441
4512
e7ac20bf3629 unset_attribute_storage, for testing purpose at least
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   442
    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
   443
        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
   444
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   445
    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
   446
        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
   447
        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
   448
        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
   449
                           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
   450
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   451
    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
   452
        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
   453
        # 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
   454
        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
   455
            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
   456
        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
   457
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
   458
    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
   459
        """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
   460
        """
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
   461
        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
   462
            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
   463
        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
   464
            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
   465
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   466
    # ISource interface #######################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   467
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   468
    @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
   469
    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
   470
        rqlst = self.repo.vreg.rqlhelper.parse(rql)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   471
        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
   472
        rqlst.children[0].solutions = sols
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   473
        self.repo.querier.sqlgen_annotate(rqlst)
438
69b79faefa94 need_intersect test and fixes
sylvain.thenault@logilab.fr
parents: 0
diff changeset
   474
        set_qdata(self.schema.rschema, rqlst, ())
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   475
        return rqlst
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   476
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   477
    def set_schema(self, schema):
2476
1294a6bdf3bf application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2354
diff changeset
   478
        """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
   479
        self._cache = QueryCache(self.repo.config['rql-cache-size'])
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   480
        self.cache_hit, self.cache_miss, self.no_cache = 0, 0, 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   481
        self.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   482
        try:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   483
            self._rql_sqlgen.schema = schema
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   484
        except AttributeError:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   485
            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
   486
        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
   487
            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
   488
        clear_cache(self, 'need_fti_indexation')
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   489
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   490
    @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
   491
    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
   492
        """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
   493
        information found in kwargs, else raise `AuthenticationError`
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   494
        """
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
   495
        for authentifier in self.authentifiers:
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   496
            try:
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
   497
                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
   498
            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
   499
                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
   500
        raise AuthenticationError()
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   501
12756
d91c229de97f [debug/rql] bind a uniq token per rql to trace its decomposition
Laurent Peuch <cortex@worlddomination.be>
parents: 12739
diff changeset
   502
    def syntax_tree_search(self, cnx, union, args=None, cachekey=None, rql_query_tracing_token=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   503
        """return result from this source for a rql query (actually from
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   504
        a rql syntax tree and a solution dictionary mapping each used
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   505
        variable to a possible type). If cachekey is given, the query
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   506
        necessary to fetch the results (but not the results themselves)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   507
        may be cached using this key.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   508
        """
11237
f32134dd0067 [repository] drop remanescence of old multi-sources code
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11135
diff changeset
   509
        assert dbg_st_search(self.uri, union, args, cachekey)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   510
        # remember number of actually selected term (sql generation may append some)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   511
        if cachekey is None:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   512
            self.no_cache += 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   513
            # 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
   514
            sql, qargs, cbs = self._rql_sqlgen.generate(union, args)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   515
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   516
            # sql may be cached
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   517
            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
   518
                sql, qargs, cbs = self._cache[cachekey]
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   519
                self.cache_hit += 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   520
            except KeyError:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   521
                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
   522
                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
   523
                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
   524
        args = self.merge_args(args, qargs)
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   525
        assert isinstance(sql, str), repr(sql)
12756
d91c229de97f [debug/rql] bind a uniq token per rql to trace its decomposition
Laurent Peuch <cortex@worlddomination.be>
parents: 12739
diff changeset
   526
        cursor = cnx.system_sql(sql, args, rql_query_tracing_token=rql_query_tracing_token)
10086
98bc2ca1a816 [source/native] session -> cnx
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10074
diff changeset
   527
        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
   528
        assert dbg_results(results)
d6012db7b93e R [server debug] more server side debugging tweaks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2620
diff changeset
   529
        return results
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   530
4964
d9e8af8a7a42 [source] implement storages right in the source rather than in hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 4943
diff changeset
   531
    @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
   532
    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
   533
        _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
   534
        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
   535
        try:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   536
            yield
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   537
        finally:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   538
            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
   539
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   540
    @contextmanager
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   541
    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
   542
        # 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
   543
        #    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
   544
        #    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
   545
        #    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
   546
        #    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
   547
        #    value once the SQL query will be executed
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   548
        restore_values = []
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   549
        if isinstance(entity, list):
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   550
            entities = entity
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   551
        else:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   552
            entities = [entity]
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   553
        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
   554
        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
   555
            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
   556
                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
   557
                    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
   558
                        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
   559
                    else:
d4bd28d5fca8 [server/sources] make sure entity._cw is a Connection before calling Storages
Julien Cristau <julien.cristau@logilab.fr>
parents: 10477
diff changeset
   560
                        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
   561
                        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
   562
                            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
   563
                            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
   564
                            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
   565
        try:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   566
            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
   567
        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
   568
            # 3/ restore original values
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   569
            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
   570
                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
   571
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   572
    def add_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   573
        """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
   574
        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
   575
            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
   576
            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
   577
            self.doexec(cnx, sql, attrs)
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   578
            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
   579
                self._record_tx_action(cnx, 'tx_entity_actions', u'C',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   580
                                       etype=entity.cw_etype, eid=entity.eid)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   581
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   582
    def update_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   583
        """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
   584
        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
   585
            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
   586
            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
   587
                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
   588
                self._record_tx_action(cnx, 'tx_entity_actions', u'U',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   589
                                       etype=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
   590
                                       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
   591
            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
   592
                                     ['cw_eid'])
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   593
            self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   594
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   595
    def delete_entity(self, cnx, entity):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   596
        """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
   597
        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
   598
            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
   599
                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
   600
                         for r in entity.e_schema.subject_relations()
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   601
                         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
   602
                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
   603
                self._record_tx_action(cnx, 'tx_entity_actions', u'D',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   604
                                       etype=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
   605
                                       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
   606
            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
   607
            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
   608
            self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   609
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   610
    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
   611
        """add a relation to the source"""
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   612
        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
   613
        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
   614
            self._record_tx_action(cnx, 'tx_relation_actions', u'A',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   615
                                   eid_from=subject, rtype=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
   616
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   617
    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
   618
        """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
   619
        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
   620
        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
   621
            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
   622
                self._record_tx_action(cnx, 'tx_relation_actions', u'A',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   623
                                       eid_from=subject, rtype=rtype, eid_to=object)
7551
2d4ba5b984dc cleanup
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7530
diff changeset
   624
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   625
    def _add_relations(self, cnx, rtype, subj_obj_list, inlined=False):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   626
        """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
   627
        sql = []
4818
9f9bfbcdecfd le patch massiveimport a été importé
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4810
diff changeset
   628
        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
   629
            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
   630
                     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
   631
            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
   632
        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
   633
            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
   634
            for subject, object in subj_obj_list:
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11763
diff changeset
   635
                etype = cnx.entity_type(subject)
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
   636
                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
   637
                    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
   638
                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
   639
                    etypes[etype] = [(subject, object)]
10662
10942ed172de [py3k] dict.iteritems → dict.items
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10651
diff changeset
   640
            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
   641
                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
   642
                         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
   643
                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
   644
                                               ['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
   645
                            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
   646
        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
   647
            self.doexecmany(cnx, statement, attrs)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   648
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   649
    def delete_relation(self, cnx, subject, rtype, object):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   650
        """delete a relation from the source"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   651
        rschema = self.schema.rschema(rtype)
12726
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   652
        # we should not issue UPDATE on inlined relations when subject is going
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   653
        # to be deleted.
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   654
        # Unless object is also going to be deleted and is not equal to the
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   655
        # subject, in this case DELETE should occur in a order which cubicweb
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   656
        # doesn't handle (yet). For example
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   657
        # cubicweb/server/test/unittest_migractions.py::MigrationCommandsTC::test_add_drop_entity_type
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   658
        # trigger such case.
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   659
        if (
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   660
            rschema.inlined and cnx.deleted_in_transaction(subject)
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   661
            and (subject == object or not cnx.deleted_in_transaction(object))
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   662
        ):
1a2c7d6397ec Avoid to update inlined relation column to NULL when deleting entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12586
diff changeset
   663
            return
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   664
        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
   665
        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
   666
            self._record_tx_action(cnx, 'tx_relation_actions', u'R',
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   667
                                   eid_from=subject, rtype=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
   668
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   669
    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
   670
        """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
   671
        if inlined:
11765
9cb215e833b0 [cnx] Use entity_type instead of entity_metas()['type']
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11763
diff changeset
   672
            table = SQL_PREFIX + cnx.entity_type(subject)
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
   673
            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
   674
            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
   675
                                                                  SQL_PREFIX)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   676
            attrs = {'eid': subject}
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   677
        else:
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   678
            attrs = {'eid_from': subject, 'eid_to': object}
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   679
            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
   680
        self.doexec(cnx, sql, attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   681
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   682
    @statsd_timeit
12756
d91c229de97f [debug/rql] bind a uniq token per rql to trace its decomposition
Laurent Peuch <cortex@worlddomination.be>
parents: 12739
diff changeset
   683
    def doexec(self, cnx, query, args=None, rollback=True, rql_query_tracing_token=None):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   684
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   685
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   686
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   687
        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
   688
        if server.DEBUG & server.DBG_SQL:
12739
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
   689
            print('exec', highlight(query, "SQL"), args, cnx.cnxset.cnx)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   690
        try:
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9492
diff changeset
   691
            # str(query) to avoid error if it's a unicode string
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   692
            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
   693
        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
   694
            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
   695
                # 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
   696
                # db schema
10178
4b33246cb43c [native] Change SQL errors log level.
Christophe de Vienne <christophe@unlish.com>
parents: 10076
diff changeset
   697
                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
   698
                          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
   699
            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
   700
                try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   701
                    cnx.cnxset.rollback()
4692
11a040e2601c [test] also hide this message during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4682
diff changeset
   702
                    if self.repo.config.mode != 'test':
10178
4b33246cb43c [native] Change SQL errors log level.
Christophe de Vienne <christophe@unlish.com>
parents: 10076
diff changeset
   703
                        self.debug('transaction has been rolled back')
12355
c703dc95c82e Fix flake8 issues since release 3.6.0
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 12290
diff changeset
   704
                except Exception:
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
                    pass
12586
afafc8fd9a45 Account for new psycopg2 exception classes mapping
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   706
            if any(cls.__name__ for cls in ex.__class__.__mro__
afafc8fd9a45 Account for new psycopg2 exception classes mapping
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   707
                   if cls.__name__ == 'IntegrityError'):
6211
e9d125fd1465 nicer error reporting for unique together constraints
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6201
diff changeset
   708
                # 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
   709
                for arg in ex.args:
9375
8e88576787c3 [schema] fix unique together index handling
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
   710
                    # postgres, sqlserver
8e88576787c3 [schema] fix unique together index handling
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9336
diff changeset
   711
                    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
   712
                    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
   713
                        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
   714
                    # old sqlite
10329
f92823a66f18 [sqlite] Fix integrity error parsing
Christophe de Vienne <christophe@unlish.com>
parents: 10272
diff changeset
   715
                    mo = re.search('columns? (.*) (?:is|are) not unique', arg)
12156
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
   716
                    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
   717
                        # 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
   718
                        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
   719
                                  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
   720
                        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
   721
                    # 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
   722
                    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
   723
                        # 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
   724
                        # 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
   725
                        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
   726
                        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
   727
                        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
   728
11926
2deb9f6cbb7b [source,native] Generalize the IntegrityError constraint parsing regex
Florent Cayré <florent.cayre@gmail.com>
parents: 11776
diff changeset
   729
                    mo = re.search(r'\bcstr[a-f0-9]{32}\b', arg)
10446
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   730
                    if mo is not None:
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   731
                        # postgresql
12614
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   732
                        raise ViolatedConstraint(cnx, cstrname=mo.group(0),
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   733
                                                 query=query)
10446
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   734
                    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
   735
                        # sqlite3 (new)
12614
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   736
                        raise ViolatedConstraint(cnx, cstrname=arg.split(':', 1)[1].strip(),
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   737
                                                 query=query)
10446
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   738
                    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
   739
                    if mo is not None:
1e6655cff5ab add IUserFriendlyError adapter for violation of check constraints
Julien Cristau <julien.cristau@logilab.fr>
parents: 10411
diff changeset
   740
                        # sqlite3 (old)
12614
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   741
                        raise ViolatedConstraint(cnx, cstrname=mo.group(1),
8ac9ac8d9143 [mod] make ViolatedConstraint actually display useful information
Laurent Peuch <cortex@worlddomination.be>
parents: 12591
diff changeset
   742
                                                 query=query)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   743
            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
   744
        return cursor
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   745
10477
ee21c559f94f implement a simple statsd logger (closes #5488711)
David Douard <david.douard@logilab.fr>
parents: 10473
diff changeset
   746
    @statsd_timeit
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   747
    def doexecmany(self, cnx, query, args):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   748
        """Execute a query.
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   749
        it's a function just so that it shows up in profiling
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   750
        """
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
   751
        if server.DEBUG & server.DBG_SQL:
12739
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
   752
            print('execmany', highlight(query, "SQL"), 'with', len(args), 'arguments',
c6f8ca03718f [debug] syntax highlight SQL and RQL debug output
Laurent Peuch <cortex@worlddomination.be>
parents: 12731
diff changeset
   753
                  cnx.cnxset.cnx)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   754
        cursor = cnx.cnxset.cu
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   755
        try:
9701
46c8d8701240 an unicode string -> a unicode string
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9492
diff changeset
   756
            # str(query) to avoid error if it's a unicode string
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   757
            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
   758
        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
   759
            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
   760
                # 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
   761
                # 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
   762
                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
   763
                              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
   764
            try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   765
                cnx.cnxset.rollback()
4692
11a040e2601c [test] also hide this message during test
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4682
diff changeset
   766
                if self.repo.config.mode != 'test':
9267
24d9b86dfa54 spelling: rollbacked -> rolled back
Rémi Cardona <remi.cardona@logilab.fr>
parents: 9131
diff changeset
   767
                    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
   768
            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
   769
                pass
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   770
            raise
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   771
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   772
    # short cut to method requiring advanced db helper usage ##################
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   773
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   774
    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
   775
        """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
   776
        """
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
        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
   778
        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
   779
        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
   780
            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
   781
                       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
   782
            return
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   783
        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
   784
                                      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
   785
        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
   786
                  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
   787
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   788
    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
   789
        """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
   790
        (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
   791
        """
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
        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
   793
            # 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
   794
            # 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
   795
            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
   796
        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
   797
        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
   798
        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
   799
                                       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
   800
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   801
    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
   802
        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
   803
        if rdef.indexed:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   804
            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
   805
        else:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   806
            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
   807
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   808
    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
   809
        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
   810
        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
   811
            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
   812
        else:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   813
            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
   814
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   815
    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
   816
        cursor = LogCursor(cnx.cnxset.cu)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   817
        self.dbhelper.create_index(cursor, table, column, unique)
1792
9eadf34fd860 delete-trailing-spaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   818
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   819
    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
   820
        cursor = LogCursor(cnx.cnxset.cu)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   821
        self.dbhelper.drop_index(cursor, table, column, unique)
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   822
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   823
    # system source interface #################################################
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   824
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   825
    def eid_type(self, cnx, eid):  # pylint: disable=E0202
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   826
        """Return the entity's type for `eid`."""
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   827
        sql = 'SELECT type FROM entities WHERE eid=%s' % eid
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   828
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   829
            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
   830
            if res is not None:
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   831
                return res[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
   832
        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
   833
            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
   834
        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
   835
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   836
    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
   837
        """ 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
   838
        overwritten in some stores"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   839
        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
   840
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
   841
    _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
   842
    _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
   843
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   844
    def add_info(self, cnx, entity, source):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   845
        """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
   846
        assert cnx.cnxset is not None
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
   847
        # begin by inserting eid/type/source into the entities table
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   848
        attrs = {'type': entity.cw_etype, 'eid': entity.eid}
9802
9f815b1f2516 [repository,tests] use the new connection api (part 1/2)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 9770
diff changeset
   849
        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
   850
        # 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
   851
29aebc1edd29 [repository] drop usage of no more necessary eschema_eid function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11005
diff changeset
   852
        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
   853
            self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   854
                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
   855
                (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
   856
            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
   857
                self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   858
                    cnx,
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   859
                    '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
   860
                    (entity.eid, eschema.eid))
11135
421520f4d516 [server] remove some pre 3.10 compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11129
diff changeset
   861
        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
   862
            self._handle_is_relation_sql(
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   863
                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
   864
                (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
   865
        # 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
   866
        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
   867
            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
   868
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   869
    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
   870
        """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
   871
        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
   872
            # 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
   873
            # one indexable attribute
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   874
            self.index_entity(cnx, entity=entity)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   875
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   876
    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
   877
        """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
   878
        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
   879
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
   880
        * update the fti
7501
2983dd24494a [repository] refactor/cleanup entity deletion methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7342
diff changeset
   881
        * remove record from the `entities` table
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
   882
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   883
        self.fti_unindex_entities(cnx, entities)
11351
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   884
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   885
        # 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
   886
        # 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
   887
        count = len(entities)
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   888
        batch_size = 10000
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   889
        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
   890
            in_eid = ",".join(str(entities[index].eid)
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   891
                              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
   892
            attrs = {'eid': '(%s)' % (in_eid,)}
97882e99138d [server] Improve massive deletion of entities
Philippe Pepiot <philippe.pepiot@logilab.fr>
parents: 11279
diff changeset
   893
            self.doexec(cnx, self.sqlgen.delete_many('entities', attrs), attrs)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   894
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   895
    # undo support #############################################################
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   896
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   897
    def undoable_transactions(self, cnx, ueid=None, **actionfilters):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
   898
        """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
   899
        # 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
   900
        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
   901
            ueid = cnx.user.eid
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   902
        restr = {}
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   903
        if ueid is not None:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   904
            restr['tx_user'] = ueid
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   905
        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
   906
        if actionfilters:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   907
            # 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
   908
            # actions done
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   909
            tearestr = {}  # filters on the tx_entity_actions table
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   910
            trarestr = {}  # filters on the tx_relation_actions table
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   911
            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
   912
            # 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
   913
            # actions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   914
            if actionfilters.pop('public', True):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   915
                genrestr['txa_public'] = True
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   916
            # 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
   917
            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
   918
                if key == 'etype':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   919
                    # 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
   920
                    # 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
   921
                    assert actionfilters.get('action', 'C') in 'CUD'
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
   922
                    assert 'eid' not in actionfilters
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   923
                    tearestr['etype'] = val
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   924
                elif key == 'eid':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   925
                    # 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
   926
                    # '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
   927
                    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
   928
                        tearestr['eid'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   929
                    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
   930
                        trarestr['eid_from'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   931
                        trarestr['eid_to'] = val
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   932
                elif key == 'action':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   933
                    if val in 'CUD':
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   934
                        tearestr['txa_action'] = val
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   935
                    else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   936
                        assert val in 'AR'
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   937
                        trarestr['txa_action'] = val
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   938
                else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   939
                    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
   940
            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
   941
            subqsqls = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   942
            # 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
   943
            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
   944
                trarestr.update(genrestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   945
                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
   946
                if 'eid_from' in trarestr:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   947
                    # 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
   948
                    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
   949
                                                     'eid_to = %(eid_to)s'])
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   950
                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
   951
                subqsqls.append('EXISTS(%s)' % trasql)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   952
            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
   953
                tearestr.update(genrestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   954
                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
   955
                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
   956
                subqsqls.append('EXISTS(%s)' % teasql)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   957
            if restr:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   958
                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
   959
            else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   960
                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
   961
            restr.update(trarestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   962
            restr.update(tearestr)
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   963
        # 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
   964
        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
   965
        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
   966
        # turn results into transaction objects
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
   967
        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
   968
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   969
    def tx_info(self, cnx, txuuid):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
   970
        """See :class:`cubicweb.repoapi.Connection.transaction_info`"""
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
   971
        return tx.Transaction(cnx, txuuid, *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
   972
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   973
    def tx_actions(self, cnx, txuuid, public):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
   974
        """See :class:`cubicweb.repoapi.Connection.transaction_actions`"""
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   975
        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
   976
        restr = {'tx_uuid': txuuid}
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   977
        if public:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   978
            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
   979
        # 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
   980
        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
   981
                                 ('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
   982
                                  'etype', 'eid', 'changes'))
11429
6a9a9ea1e9b9 Remove usage of cnx.ensure_cnx_set context manager
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 11417
diff changeset
   983
        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
   984
        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
   985
                   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
   986
        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
   987
                                 ('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
   988
                                  '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
   989
        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
   990
        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
   991
        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
   992
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
   993
    def undo_transaction(self, cnx, txuuid):
10356
a009a31fb1ea [connection] eliminate ClientConnection leftovers
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10351
diff changeset
   994
        """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
   995
8631bb9f6e73 [undo] during undoing, call hooks in the [active]integrity and undo categories
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5070
diff changeset
   996
        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
   997
        '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
   998
        """
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
   999
        errors = []
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1000
        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
  1001
        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
  1002
            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
  1003
                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
  1004
                    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
  1005
                    errors += undomethod(cnx, action)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1006
        # remove the transactions record
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1007
        self.doexec(cnx,
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1008
                    "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
  1009
        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
  1010
            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
  1011
        else:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1012
            return
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1013
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1014
    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
  1015
        """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
  1016
        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
  1017
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1018
        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
  1019
        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
  1020
        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
  1021
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1022
    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
  1023
        """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
  1024
        attributes of the entity
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1025
        """
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1026
        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
  1027
        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
  1028
        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
  1029
        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
  1030
        # 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
  1031
        eschema = entity.e_schema
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1032
        for column in attrs:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1033
            # [3:] remove 'cw_' prefix
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1034
            attr = column[3:]
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1035
            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
  1036
                continue
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1037
            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
  1038
                value = values[column]
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1039
                if value is not None:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1040
                    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
  1041
        return values
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1042
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1043
    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
  1044
        """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
  1045
        '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
  1046
        """
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1047
        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
  1048
        kwargs['txa_action'] = action
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1049
        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
  1050
        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
  1051
        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
  1052
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1053
    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
  1054
        """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
  1055
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1056
        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
  1057
        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
  1058
        """
10365
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1059
        restr = {'tx_uuid': txuuid}
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1060
        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
  1061
                                 ('tx_time', 'tx_user'))
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1062
        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
  1063
        try:
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1064
            time, ueid = cu.fetchone()
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1065
        except TypeError:
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1066
            raise tx.NoSuchTransaction(txuuid)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1067
        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
  1068
                or cnx.user.eid == ueid):
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1069
            raise tx.NoSuchTransaction(txuuid)
21461f80f348 [connection] remove ensure_cnx_set context manager uses
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10364
diff changeset
  1070
        return time, ueid
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1071
8265
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1072
    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
  1073
        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
  1074
        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
  1075
        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
  1076
        # 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
  1077
        # 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
  1078
        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
  1079
        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
  1080
        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
  1081
            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
  1082
            if rtype == "eid":
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1083
                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
  1084
            try:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1085
                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
  1086
            except KeyError:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1087
                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
  1088
                          "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
  1089
                    % {'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
  1090
            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
  1091
                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
  1092
                    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
  1093
                # 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
  1094
                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
  1095
                    # 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
  1096
                    try:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1097
                        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
  1098
                        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
  1099
                    except UnknownEid:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1100
                        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
  1101
                                  "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
  1102
                            % 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
  1103
                        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
  1104
            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
  1105
                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
  1106
                edited[rtype] = 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
  1107
            else:
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1108
                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
  1109
        # 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
  1110
        # 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
  1111
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1112
    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
  1113
        """undo an entity deletion"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1114
        errors = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1115
        err = errors.append
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1116
        eid = action.eid
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1117
        etype = action.etype
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1118
        # get an entity instance
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1119
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1120
            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
  1121
        except Exception:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1122
            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
  1123
                % (eid, etype))
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1124
            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
  1125
        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
  1126
        entity.eid = eid
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1127
        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
  1128
        entity.cw_edited.check()
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1129
        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
  1130
        # restore the entity
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1131
        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
  1132
        # restore record in entities (will update fti if needed)
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
  1133
        self.add_info(cnx, entity, self)
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1134
        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
  1135
        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
  1136
        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
  1137
        return errors
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1138
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1139
    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
  1140
        """undo a relation removal"""
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1141
        errors = []
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1142
        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
  1143
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1144
            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
  1145
        except _UndoException as ex:
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
  1146
            errors.append(str(ex))
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1147
        else:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1148
            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
  1149
                                 ('object', oentity)):
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1150
                try:
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1151
                    _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
  1152
                except _UndoException as ex:
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
  1153
                    errors.append(str(ex))
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1154
                    continue
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1155
        if not errors:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1156
            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
  1157
                                    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
  1158
            # 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
  1159
            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
  1160
            # set related cache
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1161
            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
  1162
            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
  1163
                                    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
  1164
        return errors
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
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_c(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 creation"""
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1168
        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
  1169
        # 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
  1170
        # 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
  1171
        # massive deletion performance)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1172
        if _undo_has_later_transaction(cnx, eid):
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1173
            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
  1174
            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
  1175
        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
  1176
        # 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
  1177
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1178
            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
  1179
        except Exception:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1180
            return [cnx._(
5098
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1181
                "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
  1182
                "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
  1183
        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
  1184
        # 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
  1185
        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
  1186
        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
  1187
        # 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
  1188
        # unvisible as transaction action
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1189
        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
  1190
        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
  1191
        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
  1192
        # 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
  1193
        # 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
  1194
        attrs = {'cw_eid': eid}
8900
010a59e12d89 use cw_etype instead of __regid__
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 8821
diff changeset
  1195
        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
  1196
        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
  1197
        # 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
  1198
        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
  1199
        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
  1200
        return ()
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1201
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1202
    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
  1203
        """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
  1204
        errors = []
9747ab9230ad [repo, undo] Finish repository-side implementation of the undo feature (closes #893940)
Anthony Truchet <anthony.truchet@logilab.fr>
parents: 8235
diff changeset
  1205
        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
  1206
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1207
            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
  1208
        except UnknownEid:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1209
            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
  1210
                      "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
  1211
            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
  1212
        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
  1213
        entity.cw_edited.check()
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1214
        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
  1215
        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
  1216
                                 ['cw_eid'])
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1217
        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
  1218
        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
  1219
        return errors
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1220
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1221
    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
  1222
        """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
  1223
        errors = []
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1224
        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
  1225
        try:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1226
            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
  1227
        except _UndoException as ex:
12567
26744ad37953 Drop python2 support
Denis Laxalde <denis.laxalde@logilab.fr>
parents: 12355
diff changeset
  1228
            errors.append(str(ex))
5076
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1229
        else:
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1230
            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
  1231
            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
  1232
                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
  1233
                      % (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
  1234
            else:
b0e6134b4324 [undo] basic support for undoing of entity creation / relation addition
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5075
diff changeset
  1235
                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
  1236
                      % (rtype, subj, obj)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1237
            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
  1238
            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
  1239
                errors.append(cnx._(
5098
32b1adfb6b92 [i18n] use named substitution to avoid gettext warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5076
diff changeset
  1240
                    "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
  1241
                    " %(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
  1242
        if not errors:
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1243
            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
  1244
                                    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
  1245
            # 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
  1246
            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
  1247
            # set related cache
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1248
            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
  1249
            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
  1250
                                    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
  1251
        return errors
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1252
4806
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1253
    # full text index handling #################################################
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1254
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1255
    @cached
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1256
    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
  1257
        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
  1258
        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
  1259
            return True
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1260
        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
  1261
            return True
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1262
        return False
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1263
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1264
    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
  1265
        """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
  1266
        on commit
5642bfa43236 [cleanup] add index_entity to abstract source, add docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4806
diff changeset
  1267
        """
10631
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
  1268
        if self.do_fti:
1ab79c435fae consider .do_fti flag in index_entity method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 10329
diff changeset
  1269
            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
  1270
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1271
    def fti_unindex_entities(self, cnx, entities):
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1272
        """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
  1273
        """
12290
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1274
        if not cnx.repo.system_source.do_fti:
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1275
            return
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1276
        cursor = cnx.cnxset.cu
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1277
        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
  1278
        try:
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1279
            for entity in entities:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1280
                cursor_unindex_object(entity.eid, cursor)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1281
        except Exception:  # let KeyboardInterrupt / SystemExit propagate
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1282
            self.exception('error while unindexing %s', entity)
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1283
9574
2d4c4842bd04 [server] some s/session/cnx/
Julien Cristau <julien.cristau@logilab.fr>
parents: 9546
diff changeset
  1284
    def fti_index_entities(self, cnx, entities):
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1285
        """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
  1286
        """
12290
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1287
        if not cnx.repo.system_source.do_fti:
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1288
            return
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1289
        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
  1290
        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
  1291
        try:
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1292
            # 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
  1293
            # unindexing done in the FTIndexEntityOp
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1294
            for entity in entities:
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1295
                cursor_index_object(entity.eid,
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1296
                                    entity.cw_adapt_to('IFTIndexable'),
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1297
                                    cursor)
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1298
        except Exception:  # let KeyboardInterrupt / SystemExit propagate
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1299
            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
  1300
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1301
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
  1302
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
  1303
    """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
  1304
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1305
    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
  1306
    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
  1307
    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
  1308
    """
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1309
4f12f59b1a13 [fti] refactor and fix full text indexation handling
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4692
diff changeset
  1310
    def precommit_event(self):
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1311
        cnx = self.cnx
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1312
        source = cnx.repo.system_source
12290
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1313
        if not source.do_fti:
2b049c9fcec5 [source/native] do NOT do anything with fti if do_fti is False
David Douard <david.douard@logilab.fr>
parents: 12156
diff changeset
  1314
            return
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1315
        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
  1316
        done = cnx.transaction_data.setdefault('indexedeids', set())
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1317
        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
  1318
        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
  1319
            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
  1320
                # 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
  1321
                # processed
6889
37668bf302f5 improve massive deletion performance
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 6850
diff changeset
  1322
                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
  1323
            done.add(eid)
9611
ca853478aaa8 [server/sources/native] deal with connections, not sessions
Julien Cristau <julien.cristau@logilab.fr>
parents: 9605
diff changeset
  1324
            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
  1325
            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
  1326
        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
  1327
        source.fti_index_entities(cnx, to_reindex)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1328
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1329
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1330
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
  1331
    """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
  1332
    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
  1333
    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
  1334
    # 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
  1335
    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
  1336
        yield sql
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1337
    for sql in ("""
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1338
CREATE TABLE entities (
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1339
  eid INTEGER PRIMARY KEY NOT NULL,
11774
51c160677afe [repository] Drop the entities.extid column and associated cache
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11773
diff changeset
  1340
  type VARCHAR(64) NOT NULL
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1341
);;
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1342
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1343
CREATE TABLE transactions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1344
  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
  1345
  tx_user INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1346
  tx_time %s NOT NULL
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1347
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1348
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
  1349
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
  1350
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1351
CREATE TABLE tx_entity_actions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1352
  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
  1353
  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
  1354
  txa_public %s NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1355
  txa_order INTEGER,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1356
  eid INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1357
  etype VARCHAR(64) NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1358
  changes %s
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1359
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1360
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
  1361
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
  1362
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
  1363
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
  1364
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
  1365
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1366
CREATE TABLE tx_relation_actions (
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1367
  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
  1368
  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
  1369
  txa_public %s NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1370
  txa_order INTEGER,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1371
  eid_from INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1372
  eid_to INTEGER NOT NULL,
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1373
  rtype VARCHAR(256) NOT NULL
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1374
);;
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1375
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
  1376
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
  1377
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
  1378
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
  1379
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
  1380
""" % (typemap['Datetime'],
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1381
       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
  1382
        yield sql
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1383
    if helper.backend_name == 'sqlite':
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1384
        # 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
  1385
        yield '''
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1386
CREATE TRIGGER fkd_transactions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1387
BEFORE DELETE ON transactions
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1388
FOR EACH ROW BEGIN
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1389
    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
  1390
    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
  1391
END;
4913
083b4d454192 server/web api for accessing to deleted_entites
Katia Saurfelt <katia.saurfelt@logilab.fr>
parents: 4902
diff changeset
  1392
'''
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1393
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1394
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
  1395
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
  1396
    """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
  1397
    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
  1398
    """
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
  1399
    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
  1400
                  '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
  1401
        if set_owner:
11413
c172fa18565e [schema2sql] Avoid "parsing" SQL statements for database initialization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11412
diff changeset
  1402
            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
  1403
        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
  1404
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
  1405
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
  1406
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
  1407
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
  1408
    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
  1409
        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
  1410
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
  1411
    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
  1412
        """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
  1413
        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
  1414
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1415
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
  1416
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
  1417
    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
  1418
    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
  1419
                '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
  1420
    _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
  1421
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
  1422
    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
  1423
        """set the instance'schema"""
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1424
        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
  1425
            # 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
  1426
            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
  1427
            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
  1428
9512
88dc96fc9fc1 [server] use a connection instead of a session for user authentication
Julien Cristau <julien.cristau@logilab.fr>
parents: 9487
diff changeset
  1429
    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
  1430
        """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
  1431
        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
  1432
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
  1433
        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
  1434
        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
  1435
        """
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1436
        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
  1437
        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
  1438
            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
  1439
            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
  1440
                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
  1441
            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
  1442
                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
  1443
            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
  1444
                # 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
  1445
                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
  1446
            # 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
  1447
            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
  1448
        # 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
  1449
        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
  1450
        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
  1451
        try:
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1452
            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
  1453
            # 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
  1454
            # 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
  1455
            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
  1456
                verify, newhash = verify_and_update(password, pwd.getvalue())
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1457
                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
  1458
                    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
  1459
                if newhash:
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1460
                    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
  1461
                                   % (SQL_PREFIX + 'CWUser',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1462
                                      SQL_PREFIX + 'upassword',
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1463
                                      SQL_PREFIX + 'login'),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1464
                                   {'newhash': self.source._binary(newhash.encode('ascii')),
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1465
                                    'login': login})
10364
8b35a898b334 [server] remove cnxset tracking, it is now unneeded
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10360
diff changeset
  1466
                    cnx.commit()
8546
3d2038d6f20d [sources/native] automatically update passwords using deprecated hashes on login
Julien Cristau <julien.cristau@logilab.fr>
parents: 8520
diff changeset
  1467
            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
  1468
        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
  1469
            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
  1470
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
  1471
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
  1472
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
  1473
    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
  1474
        # 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
  1475
        # 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
  1476
        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
  1477
            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
  1478
        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
  1479
                           'M address %(login)s', {'login': login},
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1480
                           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
  1481
        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
  1482
            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
  1483
        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
  1484
        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
  1485
        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
  1486
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1487
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1488
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
  1489
    """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
  1490
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1491
    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
  1492
    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
  1493
    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
  1494
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1495
    * 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
  1496
    * 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
  1497
    * 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
  1498
    * 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
  1499
    * 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
  1500
    * 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
  1501
    * 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
  1502
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1503
    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
  1504
    * 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
  1505
    * 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
  1506
    * 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
  1507
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1508
    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
  1509
    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
  1510
    """
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
  1511
    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
  1512
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1513
    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
  1514
        """
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1515
        :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
  1516
        """
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1517
        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
  1518
        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
  1519
        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
  1520
        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
  1521
        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
  1522
        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
  1523
        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
  1524
        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
  1525
        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
  1526
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1527
    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
  1528
        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
  1529
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1530
    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
  1531
        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
  1532
        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
  1533
        try:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1534
            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
  1535
            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
  1536
            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
  1537
            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
  1538
            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
  1539
                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
  1540
                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
  1541
            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
  1542
                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
  1543
                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
  1544
            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
  1545
                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
  1546
                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
  1547
        finally:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1548
            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
  1549
            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
  1550
        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
  1551
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1552
    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
  1553
        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
  1554
                             'transactions',
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1555
                             '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
  1556
                             '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
  1557
                             ]
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1558
        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
  1559
        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
  1560
        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
  1561
        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
  1562
            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
  1563
            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
  1564
                continue
11417
5e5e224239c3 pep8 bits
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 11413
diff changeset
  1565
            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
  1566
        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
  1567
            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
  1568
            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
  1569
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1570
            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
  1571
        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
  1572
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 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
  1574
        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
  1575
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
  1576
    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
  1577
        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
  1578
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1579
    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
  1580
        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
  1581
        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
  1582
        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
  1583
        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
  1584
        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
  1585
        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
  1586
                                 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
  1587
        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
  1588
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1589
    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
  1590
        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
  1591
        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
  1592
        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
  1593
        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
  1594
        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
  1595
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
  1596
    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
  1597
        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
  1598
        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
  1599
        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
  1600
        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
  1601
        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
  1602
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1603
    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
  1604
        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
  1605
        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
  1606
        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
  1607
        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
  1608
        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
  1609
        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
  1610
        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
  1611
        if rowcount > 0:
10609
e2d8e81bfe68 [py3k] import range using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10602
diff changeset
  1612
            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
  1613
                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
  1614
                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
  1615
                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
  1616
                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
  1617
                                  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
  1618
                                  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
  1619
                                  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
  1620
        else:
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1621
            rows = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1622
            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
  1623
            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
  1624
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1625
    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
  1626
        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
  1627
        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
  1628
        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
  1629
        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
  1630
        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
  1631
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1632
    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
  1633
        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
  1634
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1635
    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
  1636
        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
  1637
        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
  1638
        self.cursor = self.cnx.cursor()
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1639
        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
  1640
        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
  1641
            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
  1642
            self.read_sequence(archive, seq)
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1643
        for numrange in numranges:
10623
b9322cc17d7e [sources/native] fix potential NameError (closes #7364249)
Aurelien Campeas <aurelien.campeas@pythonian.fr>
parents: 10270
diff changeset
  1644
            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
  1645
            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
  1646
        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
  1647
            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
  1648
            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
  1649
        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
  1650
        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
  1651
        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
  1652
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1653
    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
  1654
        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
  1655
        self.logger.info('checking metadata')
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1656
        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
  1657
            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
  1658
            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
  1659
        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
  1660
        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
  1661
        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
  1662
        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
  1663
        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
  1664
        if archive_versions != db_versions:
11115
a385bd146178 [sources/native] remove extra space before colon
Julien Cristau <julien.cristau@logilab.fr>
parents: 11060
diff changeset
  1665
            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
  1666
            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
  1667
            if new_cubes:
12156
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
  1668
                self.logger.critical('In the db:\n%s', '\n'.join(
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
  1669
                    '%s: %s' % (cube, ver) for cube, ver in sorted(new_cubes)))
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
  1670
            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
  1671
            if old_cubes:
12156
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
  1672
                self.logger.critical('In the archive:\n%s', '\n'.join(
0d1d22a3a48b Fix some flake8 errors
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 12153
diff changeset
  1673
                    '%s: %s' % (cube, ver) for cube, ver in sorted(old_cubes)))
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
  1674
            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
  1675
                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
  1676
        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
  1677
        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
  1678
            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
  1679
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1680
            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
  1681
            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
  1682
            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
  1683
        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
  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 read_sequence(self, archive, seq):
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1686
        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
  1687
        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
  1688
        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
  1689
        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
  1690
        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
  1691
        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
  1692
        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
  1693
        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
  1694
10197
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1695
    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
  1696
        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
  1697
        assert rangename == numrange
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1698
        assert len(rows) == 1
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1699
        assert len(rows[0]) == 1
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1700
        value = rows[0][0]
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1701
        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
  1702
        self.cursor.execute(sql)
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1703
        self.cnx.commit()
7c732d2abbc1 [restore/portable] properly restore the numrange generator
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 10196
diff changeset
  1704
7342
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1705
    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
  1706
        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
  1707
        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
  1708
        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
  1709
        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
  1710
        for filename in filenames:
10602
4845012cfc8e [py3k] import 'pickle' using six.moves
Rémi Cardona <remi.cardona@logilab.fr>
parents: 10589
diff changeset
  1711
            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
  1712
            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
  1713
            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
  1714
                continue
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1715
            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
  1716
                                               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
  1717
            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
  1718
                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
  1719
            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
  1720
            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
  1721
        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
  1722
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1723
    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
  1724
        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
  1725
        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
  1726
            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
  1727
        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
  1728
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1729
    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
  1730
        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
  1731
        versions = []
d1c8b5b3531c adds support for a portable db import/export format (closes: #1521112)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7243
diff changeset
  1732
        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
  1733
        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
  1734
            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
  1735
                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
  1736
        return versions