0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 1
"""Helper classes to execute RQL queries on a set of sources, performing
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 2
security checking and data aggregation.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 3
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 4
:organization: Logilab
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 5
:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 6
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 7
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 8
__docformat__ = "restructuredtext en"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 9
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 10
from itertools import repeat
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 11
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 12
from logilab.common.cache import Cache
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 13
from logilab.common.compat import any
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 14
from rql import RQLHelper , RQLSyntaxError
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 15
from rql.stmts import Union , Select
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 16
from rql.nodes import ( Relation , VariableRef , Constant , Exists , Variable ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 17
SubQuery )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 18
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 19
from cubicweb import Unauthorized , QueryError , UnknownEid , typed_eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 20
from cubicweb import server
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 21
from cubicweb.rset import ResultSet
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 22
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 23
from cubicweb.server.utils import cleanup_solutions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 24
from cubicweb.server.rqlannotation import SQLGenAnnotator , set_qdata
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 25
from cubicweb.server.ssplanner import add_types_restriction
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 26
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 27
def empty_rset ( session , rql , args , rqlst = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 28
"""build an empty result set object"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 29
return ResultSet ([], rql , args , rqlst = rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 30
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 31
def update_varmap ( varmap , selected , table ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 32
"""return a sql schema to store RQL query result"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 33
for i , term in enumerate ( selected ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 34
key = term . as_string ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 35
value = ' %s .C %s ' % ( table , i )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 36
if varmap . get ( key , value ) != value :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 37
raise Exception ( 'variable name conflict on %s ' % key )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 38
varmap [ key ] = value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 39
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 40
# permission utilities ########################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 41
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 42
def var_kwargs ( restriction , args ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 43
varkwargs = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 44
for rel in restriction . iget_nodes ( Relation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 45
cmp = rel . children [ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 46
if rel . r_type == 'eid' and cmp . operator == '=' and \
389
+ − 47
not rel . neged ( strict = True ) and \
321
+ − 48
isinstance ( cmp . children [ 0 ], Constant ) and \
+ − 49
cmp . children [ 0 ] . type == 'Substitute' :
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 50
varkwargs [ rel . children [ 0 ] . name ] = typed_eid ( cmp . children [ 0 ] . eval ( args ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 51
return varkwargs
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 52
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 53
def check_no_password_selected ( rqlst ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 54
"""check that Password entities are not selected"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 55
for solution in rqlst . solutions :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 56
if 'Password' in solution . itervalues ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 57
raise Unauthorized ( 'Password selection is not allowed' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 58
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 59
def check_read_access ( schema , user , rqlst , solution ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 60
"""check that the given user has credentials to access data read the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 61
query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 62
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 63
return a dict defining necessary local checks (due to use of rql expression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 64
in the schema), keys are variable names and values associated rql expression
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 65
for the associated variable with the given solution
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 66
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 67
if rqlst . where is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 68
for rel in rqlst . where . iget_nodes ( Relation ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 69
# XXX has_text may have specific perm ?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 70
if rel . r_type in ( 'is' , 'is_instance_of' , 'has_text' , 'identity' , 'eid' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 71
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 72
if not schema . rschema ( rel . r_type ) . has_access ( user , 'read' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 73
raise Unauthorized ( 'read' , rel . r_type )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 74
localchecks = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 75
# iterate on defined_vars and not on solutions to ignore column aliases
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 76
for varname in rqlst . defined_vars :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 77
etype = solution [ varname ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 78
eschema = schema . eschema ( etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 79
if not eschema . has_access ( user , 'read' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 80
erqlexprs = eschema . get_rqlexprs ( 'read' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 81
if not erqlexprs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 82
ex = Unauthorized ( 'read' , etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 83
ex . var = varname
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 84
raise ex
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 85
#assert len(erqlexprs) == 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 86
localchecks [ varname ] = tuple ( erqlexprs )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 87
return localchecks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 88
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 89
def noinvariant_vars ( restricted , select , nbtrees ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 90
# a variable can actually be invariant if it has not been restricted for
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 91
# security reason or if security assertion hasn't modified the possible
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 92
# solutions for the query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 93
if nbtrees != 1 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 94
for vname in restricted :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 95
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 96
yield select . defined_vars [ vname ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 97
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 98
# this is an alias
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 99
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 100
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 101
for vname in restricted :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 102
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 103
var = select . defined_vars [ vname ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 104
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 105
# this is an alias
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 106
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 107
if len ( var . stinfo [ 'possibletypes' ]) != 1 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 108
yield var
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 109
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 110
def _expand_selection ( terms , selected , aliases , select , newselect ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 111
for term in terms :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 112
for vref in term . iget_nodes ( VariableRef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 113
if not vref . name in selected :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 114
select . append_selected ( vref )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 115
colalias = newselect . get_variable ( vref . name , len ( aliases ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 116
aliases . append ( VariableRef ( colalias ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 117
selected . add ( vref . name )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 118
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 119
# Plans #######################################################################
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 120
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 121
class ExecutionPlan ( object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 122
"""the execution model of a rql query, composed of querier steps"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 123
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 124
def __init__ ( self , querier , rqlst , args , session ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 125
# original rql syntax tree
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 126
self . rqlst = rqlst
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 127
self . args = args or {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 128
# session executing the query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 129
self . session = session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 130
# quick reference to the system source
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 131
self . syssource = session . pool . source ( 'system' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 132
# execution steps
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 133
self . steps = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 134
# index of temporary tables created during execution
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 135
self . temp_tables = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 136
# various resource accesors
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 137
self . querier = querier
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 138
self . schema = querier . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 139
self . rqlhelper = querier . _rqlhelper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 140
self . sqlannotate = querier . sqlgen_annotate
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 141
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 142
def annotate_rqlst ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 143
if not self . rqlst . annotated :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 144
self . rqlhelper . annotate ( self . rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 145
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 146
def add_step ( self , step ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 147
"""add a step to the plan"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 148
self . steps . append ( step )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 149
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 150
def clean ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 151
"""remove temporary tables"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 152
self . syssource . clean_temp_data ( self . session , self . temp_tables )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 153
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 154
def sqlexec ( self , sql , args = None ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 155
return self . syssource . sqlexec ( self . session , sql , args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 156
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 157
def execute ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 158
"""execute a plan and return resulting rows"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 159
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 160
for step in self . steps :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 161
result = step . execute ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 162
# the latest executed step contains the full query result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 163
return result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 164
finally :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 165
self . clean ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 166
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 167
def init_temp_table ( self , table , selected , sol ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 168
"""initialize sql schema and variable map for a temporary table which
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 169
will be used to store result for the given rqlst
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 170
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 171
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 172
outputmap , sqlschema , _ = self . temp_tables [ table ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 173
update_varmap ( outputmap , selected , table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 174
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 175
sqlschema , outputmap = self . syssource . temp_table_def ( selected , sol ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 176
table )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 177
self . temp_tables [ table ] = [ outputmap , sqlschema , False ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 178
return outputmap
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 179
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 180
def create_temp_table ( self , table ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 181
"""create a temporary table to store result for the given rqlst"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 182
if not self . temp_tables [ table ][ - 1 ]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 183
sqlschema = self . temp_tables [ table ][ 1 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 184
self . syssource . create_temp_table ( self . session , table , sqlschema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 185
self . temp_tables [ table ][ - 1 ] = True
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 186
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 187
def preprocess ( self , union , security = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 188
"""insert security when necessary then annotate rql st for sql generation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 189
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 190
return rqlst to actually execute
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 191
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 192
#if server.DEBUG:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 193
# print '------- preprocessing', union.as_string('utf8')
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 194
noinvariant = set ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 195
if security and not self . session . is_super_session :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 196
self . _insert_security ( union , noinvariant )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 197
self . rqlhelper . simplify ( union )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 198
self . sqlannotate ( union )
438
+ − 199
set_qdata ( self . schema . rschema , union , noinvariant )
0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 200
if union . has_text_query :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 201
self . cache_key = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 202
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 203
def _insert_security ( self , union , noinvariant ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 204
rh = self . rqlhelper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 205
for select in union . children [:]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 206
for subquery in select . with_ :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 207
self . _insert_security ( subquery . query , noinvariant )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 208
localchecks , restricted = self . _check_permissions ( select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 209
if any ( localchecks ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 210
rewrite = self . session . rql_rewriter . rewrite
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 211
nbtrees = len ( localchecks )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 212
myunion = union
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 213
# transform in subquery when len(localchecks)>1 and groups
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 214
if nbtrees > 1 and ( select . orderby or select . groupby or
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 215
select . having or select . has_aggregat or
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 216
select . limit or select . offset ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 217
newselect = Select ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 218
# only select variables in subqueries
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 219
origselection = select . selection
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 220
select . select_only_variables ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 221
select . has_aggregat = False
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 222
# create subquery first so correct node are used on copy
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 223
# (eg ColumnAlias instead of Variable)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 224
aliases = [ VariableRef ( newselect . get_variable ( vref . name , i ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 225
for i , vref in enumerate ( select . selection )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 226
selected = set ( vref . name for vref in aliases )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 227
# now copy original selection and groups
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 228
for term in origselection :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 229
newselect . append_selected ( term . copy ( newselect ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 230
if select . orderby :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 231
newselect . set_orderby ([ s . copy ( newselect ) for s in select . orderby ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 232
_expand_selection ( select . orderby , selected , aliases , select , newselect )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 233
select . orderby = () # XXX dereference?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 234
if select . groupby :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 235
newselect . set_groupby ([ g . copy ( newselect ) for g in select . groupby ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 236
_expand_selection ( select . groupby , selected , aliases , select , newselect )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 237
select . groupby = () # XXX dereference?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 238
if select . having :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 239
newselect . set_having ([ g . copy ( newselect ) for g in select . having ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 240
_expand_selection ( select . having , selected , aliases , select , newselect )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 241
select . having = () # XXX dereference?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 242
if select . limit :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 243
newselect . limit = select . limit
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 244
select . limit = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 245
if select . offset :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 246
newselect . offset = select . offset
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 247
select . offset = 0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 248
myunion = Union ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 249
newselect . set_with ([ SubQuery ( aliases , myunion )], check = False )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 250
solutions = [ sol . copy () for sol in select . solutions ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 251
cleanup_solutions ( newselect , solutions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 252
newselect . set_possible_types ( solutions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 253
# if some solutions doesn't need rewriting, insert original
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 254
# select as first union subquery
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 255
if () in localchecks :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 256
myunion . append ( select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 257
# we're done, replace original select by the new select with
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 258
# subqueries (more added in the loop below)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 259
union . replace ( select , newselect )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 260
elif not () in localchecks :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 261
union . remove ( select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 262
for lcheckdef , lchecksolutions in localchecks . iteritems ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 263
if not lcheckdef :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 264
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 265
myrqlst = select . copy ( solutions = lchecksolutions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 266
myunion . append ( myrqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 267
# in-place rewrite + annotation / simplification
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 268
rewrite ( myrqlst , lcheckdef , lchecksolutions , self . args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 269
noinvariant . update ( noinvariant_vars ( restricted , myrqlst , nbtrees ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 270
if () in localchecks :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 271
select . set_possible_types ( localchecks [()])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 272
add_types_restriction ( self . schema , select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 273
noinvariant . update ( noinvariant_vars ( restricted , select , nbtrees ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 274
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 275
def _check_permissions ( self , rqlst ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 276
"""return a dict defining "local checks", e.g. RQLExpression defined in
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 277
the schema that should be inserted in the original query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 278
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 279
solutions where a variable has a type which the user can't definitly read
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 280
are removed, else if the user may read it (eg if an rql expression is
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 281
defined for the "read" permission of the related type), the local checks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 282
dict for the solution is updated
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 283
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 284
return a dict with entries for each different local check necessary,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 285
with associated solutions as value. A local check is defined by a list
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 286
of 2-uple, with variable name as first item and the necessary rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 287
expression as second item for each variable which has to be checked.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 288
So solutions which don't require local checks will be associated to
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 289
the empty tuple key.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 290
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 291
note: rqlst should not have been simplified at this point
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 292
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 293
assert not self . session . is_super_session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 294
user = self . session . user
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 295
schema = self . schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 296
msgs = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 297
# dictionnary of variables restricted for security reason
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 298
localchecks = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 299
if rqlst . where is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 300
varkwargs = var_kwargs ( rqlst . where , self . args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 301
neweids = self . session . query_data ( 'neweids' , ())
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 302
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 303
varkwargs = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 304
restricted_vars = set ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 305
newsolutions = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 306
for solution in rqlst . solutions :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 307
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 308
localcheck = check_read_access ( schema , user , rqlst , solution )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 309
except Unauthorized , ex :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 310
msg = 'remove %s from solutions since %s has no %s access to %s '
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 311
msg %= ( solution , user . login , ex . args [ 0 ], ex . args [ 1 ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 312
msgs . append ( msg )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 313
LOGGER . info ( msg )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 314
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 315
newsolutions . append ( solution )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 316
if varkwargs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 317
# try to benefit of rqlexpr.check cache for entities which
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 318
# are specified by eid in query'args
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 319
for varname , eid in varkwargs . iteritems ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 320
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 321
rqlexprs = localcheck . pop ( varname )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 322
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 323
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 324
if eid in neweids :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 325
continue
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 326
for rqlexpr in rqlexprs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 327
if rqlexpr . check ( self . session , eid ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 328
break
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 329
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 330
raise Unauthorized ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 331
restricted_vars . update ( localcheck )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 332
localchecks . setdefault ( tuple ( localcheck . iteritems ()), []) . append ( solution )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 333
# raise Unautorized exception if the user can't access to any solution
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 334
if not newsolutions :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 335
raise Unauthorized ( ' \n ' . join ( msgs ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 336
rqlst . set_possible_types ( newsolutions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 337
return localchecks , restricted_vars
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 338
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 339
def finalize ( self , select , solutions , insertedvars ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 340
rqlst = Union ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 341
rqlst . append ( select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 342
for mainvarname , rschema , newvarname in insertedvars :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 343
nvartype = str ( rschema . objects ( solutions [ 0 ][ mainvarname ])[ 0 ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 344
for sol in solutions :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 345
sol [ newvarname ] = nvartype
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 346
select . clean_solutions ( solutions )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 347
self . rqlhelper . annotate ( rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 348
self . preprocess ( rqlst , security = False )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 349
return rqlst
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 350
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 351
class InsertPlan ( ExecutionPlan ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 352
"""an execution model specific to the INSERT rql query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 353
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 354
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 355
def __init__ ( self , querier , rqlst , args , session ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 356
ExecutionPlan . __init__ ( self , querier , rqlst , args , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 357
# save originaly selected variable, we may modify this
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 358
# dictionary for substitution (query parameters)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 359
self . selected = rqlst . selection
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 360
# list of new or updated entities definition (utils.Entity)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 361
self . e_defs = [[]]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 362
# list of new relation definition (3-uple (from_eid, r_type, to_eid)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 363
self . r_defs = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 364
# indexes to track entity definitions bound to relation definitions
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 365
self . _r_subj_index = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 366
self . _r_obj_index = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 367
self . _expanded_r_defs = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 368
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 369
def relation_definitions ( self , rqlst , to_build ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 370
"""add constant values to entity def, mark variables to be selected
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 371
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 372
to_select = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 373
for relation in rqlst . main_relations :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 374
lhs , rhs = relation . get_variable_parts ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 375
rtype = relation . r_type
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 376
if rtype in ( 'eid' , 'has_text' , 'is' , 'is_instance_of' , 'identity' ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 377
raise QueryError ( "can't assign to %s " % rtype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 378
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 379
edef = to_build [ str ( lhs )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 380
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 381
# lhs var is not to build, should be selected and added as an
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 382
# object relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 383
edef = to_build [ str ( rhs )]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 384
to_select . setdefault ( edef , []) . append (( rtype , lhs , 1 ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 385
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 386
if isinstance ( rhs , Constant ) and not rhs . uid :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 387
# add constant values to entity def
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 388
value = rhs . eval ( self . args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 389
eschema = edef . e_schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 390
attrtype = eschema . subject_relation ( rtype ) . objects ( eschema )[ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 391
if attrtype == 'Password' and isinstance ( value , unicode ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 392
value = value . encode ( 'UTF8' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 393
edef [ rtype ] = value
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 394
elif to_build . has_key ( str ( rhs )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 395
# create a relation between two newly created variables
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 396
self . add_relation_def (( edef , rtype , to_build [ rhs . name ]))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 397
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 398
to_select . setdefault ( edef , []) . append ( ( rtype , rhs , 0 ) )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 399
return to_select
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 400
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 401
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 402
def add_entity_def ( self , edef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 403
"""add an entity definition to build"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 404
edef . querier_pending_relations = {}
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 405
self . e_defs [ - 1 ] . append ( edef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 406
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 407
def add_relation_def ( self , rdef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 408
"""add an relation definition to build"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 409
self . r_defs . append ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 410
if not isinstance ( rdef [ 0 ], int ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 411
self . _r_subj_index . setdefault ( rdef [ 0 ], []) . append ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 412
if not isinstance ( rdef [ 2 ], int ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 413
self . _r_obj_index . setdefault ( rdef [ 2 ], []) . append ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 414
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 415
def substitute_entity_def ( self , edef , edefs ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 416
"""substitute an incomplete entity definition by a list of complete
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 417
equivalents
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 418
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 419
e.g. on queries such as ::
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 420
INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 421
WHERE U login 'admin', U login N
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 422
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 423
X will be inserted as many times as U exists, and so the X travaille Y
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 424
relations as to be added as many time as X is inserted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 425
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 426
if not edefs or not self . e_defs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 427
# no result, no entity will be created
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 428
self . e_defs = ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 429
return
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 430
# first remove the incomplete entity definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 431
colidx = self . e_defs [ 0 ] . index ( edef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 432
for i , row in enumerate ( self . e_defs [:]):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 433
self . e_defs [ i ][ colidx ] = edefs [ 0 ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 434
samplerow = self . e_defs [ i ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 435
for edef in edefs [ 1 :]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 436
row = samplerow [:]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 437
row [ colidx ] = edef
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 438
self . e_defs . append ( row )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 439
# now, see if this entity def is referenced as subject in some relation
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 440
# definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 441
if self . _r_subj_index . has_key ( edef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 442
for rdef in self . _r_subj_index [ edef ]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 443
expanded = self . _expanded ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 444
result = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 445
for exp_rdef in expanded :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 446
for edef in edefs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 447
result . append ( ( edef , exp_rdef [ 1 ], exp_rdef [ 2 ]) )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 448
self . _expanded_r_defs [ rdef ] = result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 449
# and finally, see if this entity def is referenced as object in some
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 450
# relation definition
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 451
if self . _r_obj_index . has_key ( edef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 452
for rdef in self . _r_obj_index [ edef ]:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 453
expanded = self . _expanded ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 454
result = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 455
for exp_rdef in expanded :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 456
for edef in edefs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 457
result . append ( ( exp_rdef [ 0 ], exp_rdef [ 1 ], edef ) )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 458
self . _expanded_r_defs [ rdef ] = result
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 459
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 460
def _expanded ( self , rdef ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 461
"""return expanded value for the given relation definition"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 462
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 463
return self . _expanded_r_defs [ rdef ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 464
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 465
self . r_defs . remove ( rdef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 466
return [ rdef ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 467
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 468
def relation_defs ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 469
"""return the list for relation definitions to insert"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 470
for rdefs in self . _expanded_r_defs . values ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 471
for rdef in rdefs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 472
yield rdef
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 473
for rdef in self . r_defs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 474
yield rdef
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 475
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 476
def insert_entity_defs ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 477
"""return eids of inserted entities in a suitable form for the resulting
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 478
result set, e.g.:
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 479
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 480
e.g. on queries such as ::
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 481
INSERT Personne X, Societe Y: X nom N, Y nom 'toto', X travaille Y
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 482
WHERE U login 'admin', U login N
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 483
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 484
if there is two entities matching U, the result set will look like
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 485
[(eidX1, eidY1), (eidX2, eidY2)]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 486
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 487
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 488
repo = session . repo
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 489
results = []
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 490
for row in self . e_defs :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 491
results . append ([ repo . glob_add_entity ( session , edef )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 492
for edef in row ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 493
return results
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 494
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 495
def insert_relation_defs ( self ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 496
session = self . session
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 497
repo = session . repo
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 498
for subj , rtype , obj in self . relation_defs ():
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 499
# if a string is given into args instead of an int, we get it here
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 500
if isinstance ( subj , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 501
subj = typed_eid ( subj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 502
elif not isinstance ( subj , ( int , long )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 503
subj = subj . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 504
if isinstance ( obj , basestring ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 505
obj = typed_eid ( obj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 506
elif not isinstance ( obj , ( int , long )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 507
obj = obj . eid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 508
if repo . schema . rschema ( rtype ) . inlined :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 509
entity = session . eid_rset ( subj ) . get_entity ( 0 , 0 )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 510
entity [ rtype ] = obj
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 511
repo . glob_update_entity ( session , entity )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 512
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 513
repo . glob_add_relation ( session , subj , rtype , obj )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 514
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 515
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 516
class QuerierHelper ( object ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 517
"""helper class to execute rql queries, putting all things together"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 518
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 519
def __init__ ( self , repo , schema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 520
# system info helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 521
self . _repo = repo
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 522
# application schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 523
self . set_schema ( schema )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 524
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 525
def set_schema ( self , schema ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 526
self . schema = schema
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 527
# rql parsing / analysing helper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 528
self . _rqlhelper = RQLHelper ( schema , special_relations = { 'eid' : 'uid' ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 529
'has_text' : 'fti' })
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 530
self . _rql_cache = Cache ( self . _repo . config [ 'rql-cache-size' ])
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 531
self . cache_hit , self . cache_miss = 0 , 0
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 532
# rql planner
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 533
# note: don't use repo.sources, may not be built yet, and also "admin"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 534
# isn't an actual source
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 535
if len ([ uri for uri in self . _repo . config . sources () if uri != 'admin' ]) < 2 :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 536
from cubicweb.server.ssplanner import SSPlanner
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 537
self . _planner = SSPlanner ( schema , self . _rqlhelper )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 538
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 539
from cubicweb.server.msplanner import MSPlanner
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 540
self . _planner = MSPlanner ( schema , self . _rqlhelper )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 541
# sql generation annotator
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 542
self . sqlgen_annotate = SQLGenAnnotator ( schema ) . annotate
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 543
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 544
def parse ( self , rql , annotate = False ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 545
"""return a rql syntax tree for the given rql"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 546
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 547
return self . _rqlhelper . parse ( unicode ( rql ), annotate = annotate )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 548
except UnicodeError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 549
raise RQLSyntaxError ( rql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 550
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 551
def solutions ( self , session , rqlst , args ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 552
assert session is not None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 553
def type_from_eid ( eid , type_from_eid = self . _repo . type_from_eid ,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 554
session = session ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 555
return type_from_eid ( eid , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 556
self . _rqlhelper . compute_solutions ( rqlst , { 'eid' : type_from_eid }, args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 557
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 558
def plan_factory ( self , rqlst , args , session ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 559
"""create an execution plan for an INSERT RQL query"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 560
if rqlst . TYPE == 'insert' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 561
return InsertPlan ( self , rqlst , args , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 562
return ExecutionPlan ( self , rqlst , args , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 563
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 564
def execute ( self , session , rql , args = None , eid_key = None , build_descr = True ):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 565
"""execute a rql query, return resulting rows and their description in
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 566
a `ResultSet` object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 567
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 568
* `rql` should be an unicode string or a plain ascii string
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 569
* `args` the optional parameters dictionary associated to the query
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 570
* `build_descr` is a boolean flag indicating if the description should
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 571
be built on select queries (if false, the description will be en empty
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 572
list)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 573
* `eid_key` must be both a key in args and a substitution in the rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 574
query. It should be used to enhance cacheability of rql queries.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 575
It may be a tuple for keys in args.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 576
eid_key must be providen in case where a eid substitution is providen
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 577
and resolve some ambiguity in the possible solutions infered for each
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 578
variable in the query.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 579
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 580
on INSERT queries, there will be on row with the eid of each inserted
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 581
entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 582
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 583
result for DELETE and SET queries is undefined yet
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 584
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 585
to maximize the rql parsing/analyzing cache performance, you should
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 586
always use substitute arguments in queries (eg avoid query such as
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 587
'Any X WHERE X eid 123'!)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 588
"""
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 589
if server . DEBUG :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 590
print '*' * 80
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 591
print rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 592
# parse the query and binds variables
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 593
if eid_key is not None :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 594
if not isinstance ( eid_key , ( tuple , list )):
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 595
eid_key = ( eid_key ,)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 596
cachekey = [ rql ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 597
for key in eid_key :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 598
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 599
etype = self . _repo . type_from_eid ( args [ key ], session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 600
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 601
raise QueryError ( 'bad cache key %s (no value)' % key )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 602
except TypeError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 603
raise QueryError ( 'bad cache key %s (value: %r )' % ( key , args [ key ]))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 604
except UnknownEid :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 605
# we want queries such as "Any X WHERE X eid 9999"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 606
# return an empty result instead of raising UnknownEid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 607
return empty_rset ( session , rql , args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 608
cachekey . append ( etype )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 609
cachekey = tuple ( cachekey )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 610
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 611
cachekey = rql
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 612
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 613
rqlst = self . _rql_cache [ cachekey ]
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 614
self . cache_hit += 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 615
except KeyError :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 616
self . cache_miss += 1
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 617
rqlst = self . parse ( rql )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 618
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 619
self . solutions ( session , rqlst , args )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 620
except UnknownEid :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 621
# we want queries such as "Any X WHERE X eid 9999"
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 622
# return an empty result instead of raising UnknownEid
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 623
return empty_rset ( session , rql , args , rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 624
self . _rql_cache [ cachekey ] = rqlst
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 625
orig_rqlst = rqlst
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 626
if not rqlst . TYPE == 'select' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 627
if not session . is_super_session :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 628
check_no_password_selected ( rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 629
# write query, ensure session's mode is 'write' so connections
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 630
# won't be released until commit/rollback
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 631
session . mode = 'write'
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 632
cachekey = None
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 633
else :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 634
if not session . is_super_session :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 635
for select in rqlst . children :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 636
check_no_password_selected ( select )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 637
# on select query, always copy the cached rqlst so we don't have to
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 638
# bother modifying it. This is not necessary on write queries since
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 639
# a new syntax tree is built from them.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 640
rqlst = rqlst . copy ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 641
self . _rqlhelper . annotate ( rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 642
# make an execution plan
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 643
plan = self . plan_factory ( rqlst , args , session )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 644
plan . cache_key = cachekey
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 645
self . _planner . build_plan ( plan )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 646
# execute the plan
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 647
try :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 648
results = plan . execute ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 649
except Unauthorized :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 650
# XXX this could be done in security's after_add_relation hooks
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 651
# since it's actually realy only needed there (other relations
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 652
# security is done *before* actual changes, and add/update entity
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 653
# security is done after changes but in an operation, and exception
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 654
# generated in operation's events properly generate a rollback on
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 655
# the session). Even though, this is done here for a better
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 656
# consistency: getting an Unauthorized exception means the
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 657
# transaction has been rollbacked
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 658
session . rollback ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 659
raise
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 660
# build a description for the results if necessary
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 661
descr = ()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 662
if build_descr :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 663
if rqlst . TYPE == 'select' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 664
# sample selection
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 665
descr = session . build_description ( orig_rqlst , args , results )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 666
elif rqlst . TYPE == 'insert' :
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 667
# on insert plan, some entities may have been auto-casted,
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 668
# so compute description manually even if there is only
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 669
# one solution
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 670
basedescr = [ None ] * len ( plan . selected )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 671
todetermine = zip ( xrange ( len ( plan . selected )), repeat ( False ))
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 672
descr = session . _build_descr ( results , basedescr , todetermine )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 673
# FIXME: get number of affected entities / relations on non
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 674
# selection queries ?
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 675
# return a result set object
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 676
return ResultSet ( results , rql , args , descr , eid_key , orig_rqlst )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 677
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 678
from logging import getLogger
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 679
from cubicweb import set_log_methods
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 680
LOGGER = getLogger ( 'cubicweb.querier' )
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff
changeset
+ − 681
set_log_methods ( QuerierHelper , LOGGER )