server/sqlutils.py
branchtls-sprint
changeset 1619 e4845b54a704
parent 1408 6bf19f175ea5
child 1783 b81f9761907c
equal deleted inserted replaced
1616:b081fe3d5945 1619:e4845b54a704
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     6 """
     6 """
     7 __docformat__ = "restructuredtext en"
     7 __docformat__ = "restructuredtext en"
     8 
     8 
     9 from warnings import warn
     9 from warnings import warn
    10 from datetime import datetime, timedelta
    10 from datetime import datetime, date, timedelta
    11 
    11 
    12 from logilab.common.shellutils import ProgressBar
    12 from logilab.common.shellutils import ProgressBar
    13 from logilab.common import db
    13 from logilab.common import db
    14 from logilab.common.adbh import get_adv_func_helper
    14 from logilab.common.adbh import get_adv_func_helper
    15 from logilab.common.sqlgen import SQLGenerator
    15 from logilab.common.sqlgen import SQLGenerator
    16 
    16 
    17 from indexer import get_indexer
    17 from indexer import get_indexer
    18 
    18 
    19 from cubicweb import Binary, ConfigurationError
    19 from cubicweb import Binary, ConfigurationError
       
    20 from cubicweb.utils import todate, todatetime
    20 from cubicweb.common.uilib import remove_html_tags
    21 from cubicweb.common.uilib import remove_html_tags
    21 from cubicweb.server import SQL_CONNECT_HOOKS
    22 from cubicweb.server import SQL_CONNECT_HOOKS
    22 from cubicweb.server.utils import crypt_password
    23 from cubicweb.server.utils import crypt_password
    23 
    24 
    24 
    25 
    66         w(indexer.sql_grant_user(user))
    67         w(indexer.sql_grant_user(user))
    67         w('')
    68         w('')
    68     w(grant_schema(schema, user, set_owner, skip_entities=skip_entities, prefix=SQL_PREFIX))
    69     w(grant_schema(schema, user, set_owner, skip_entities=skip_entities, prefix=SQL_PREFIX))
    69     return '\n'.join(output)
    70     return '\n'.join(output)
    70 
    71 
    71                   
    72 
    72 def sqlschema(schema, driver, text_index=True, 
    73 def sqlschema(schema, driver, text_index=True,
    73               user=None, set_owner=False,
    74               user=None, set_owner=False,
    74               skip_relations=('has_text', 'identity'), skip_entities=()):
    75               skip_relations=('has_text', 'identity'), skip_entities=()):
    75     """return the system sql schema, according to the given parameters"""
    76     """return the system sql schema, according to the given parameters"""
    76     from yams.schema2sql import schema2sql
    77     from yams.schema2sql import schema2sql
    77     from cubicweb.server.sources import native
    78     from cubicweb.server.sources import native
    84     if text_index:
    85     if text_index:
    85         indexer = get_indexer(driver)
    86         indexer = get_indexer(driver)
    86         w(indexer.sql_init_fti())
    87         w(indexer.sql_init_fti())
    87         w('')
    88         w('')
    88     dbhelper = get_adv_func_helper(driver)
    89     dbhelper = get_adv_func_helper(driver)
    89     w(schema2sql(dbhelper, schema, prefix=SQL_PREFIX, 
    90     w(schema2sql(dbhelper, schema, prefix=SQL_PREFIX,
    90                  skip_entities=skip_entities, skip_relations=skip_relations))
    91                  skip_entities=skip_entities, skip_relations=skip_relations))
    91     if dbhelper.users_support and user:
    92     if dbhelper.users_support and user:
    92         w('')
    93         w('')
    93         w(sqlgrants(schema, driver, user, text_index, set_owner,
    94         w(sqlgrants(schema, driver, user, text_index, set_owner,
    94                     skip_relations, skip_entities))
    95                     skip_relations, skip_entities))
    95     return '\n'.join(output)
    96     return '\n'.join(output)
    96 
    97 
    97                   
    98 
    98 def sqldropschema(schema, driver, text_index=True, 
    99 def sqldropschema(schema, driver, text_index=True,
    99                   skip_relations=('has_text', 'identity'), skip_entities=()):
   100                   skip_relations=('has_text', 'identity'), skip_entities=()):
   100     """return the sql to drop the schema, according to the given parameters"""
   101     """return the sql to drop the schema, according to the given parameters"""
   101     from yams.schema2sql import dropschema2sql
   102     from yams.schema2sql import dropschema2sql
   102     from cubicweb.server.sources import native
   103     from cubicweb.server.sources import native
   103     output = []
   104     output = []
   119 
   120 
   120 class SQLAdapterMixIn(object):
   121 class SQLAdapterMixIn(object):
   121     """Mixin for SQL data sources, getting a connection from a configuration
   122     """Mixin for SQL data sources, getting a connection from a configuration
   122     dictionary and handling connection locking
   123     dictionary and handling connection locking
   123     """
   124     """
   124     
   125 
   125     def __init__(self, source_config):
   126     def __init__(self, source_config):
   126         try:
   127         try:
   127             self.dbdriver = source_config['db-driver'].lower()
   128             self.dbdriver = source_config['db-driver'].lower()
   128             self.dbname = source_config['db-name']
   129             self.dbname = source_config['db-name']
   129         except KeyError:
   130         except KeyError:
   136         self.encoding = source_config.get('db-encoding', 'UTF-8')
   137         self.encoding = source_config.get('db-encoding', 'UTF-8')
   137         self.dbapi_module = db.get_dbapi_compliant_module(self.dbdriver)
   138         self.dbapi_module = db.get_dbapi_compliant_module(self.dbdriver)
   138         self.binary = self.dbapi_module.Binary
   139         self.binary = self.dbapi_module.Binary
   139         self.dbhelper = self.dbapi_module.adv_func_helper
   140         self.dbhelper = self.dbapi_module.adv_func_helper
   140         self.sqlgen = SQLGenerator()
   141         self.sqlgen = SQLGenerator()
   141         
   142 
   142     def get_connection(self, user=None, password=None):
   143     def get_connection(self, user=None, password=None):
   143         """open and return a connection to the database"""
   144         """open and return a connection to the database"""
   144         if user or self.dbuser:
   145         if user or self.dbuser:
   145             self.info('connecting to %s@%s for user %s', self.dbname,
   146             self.info('connecting to %s@%s for user %s', self.dbname,
   146                       self.dbhost or 'localhost', user or self.dbuser)
   147                       self.dbhost or 'localhost', user or self.dbuser)
   214                     # from a query result and so it is already encrypted
   215                     # from a query result and so it is already encrypted
   215                     if isinstance(value, Binary):
   216                     if isinstance(value, Binary):
   216                         value = value.getvalue()
   217                         value = value.getvalue()
   217                     else:
   218                     else:
   218                         value = crypt_password(value)
   219                         value = crypt_password(value)
       
   220                 # XXX needed for sqlite but I don't think it is for other backends
       
   221                 elif atype == 'Datetime' and isinstance(value, date):
       
   222                     value = todatetime(value)
       
   223                 elif atype == 'Date' and isinstance(value, datetime):
       
   224                     value = todate(value)
   219                 elif isinstance(value, Binary):
   225                 elif isinstance(value, Binary):
   220                     value = self.binary(value.getvalue())
   226                     value = self.binary(value.getvalue())
   221                 # XXX <3.2 bw compat
   227                 # XXX <3.2 bw compat
   222                 elif type(value) is DateTimeType:
   228                 elif type(value) is DateTimeType:
   223                     warn('found mx date time instance, please update to use datetime',
   229                     warn('found mx date time instance, please update to use datetime',
   252             return ', '.join(self.values)
   258             return ', '.join(self.values)
   253     # renamed to GROUP_CONCAT in cubicweb 2.45, keep old name for bw compat for
   259     # renamed to GROUP_CONCAT in cubicweb 2.45, keep old name for bw compat for
   254     # some time
   260     # some time
   255     cnx.create_aggregate("CONCAT_STRINGS", 1, concat_strings)
   261     cnx.create_aggregate("CONCAT_STRINGS", 1, concat_strings)
   256     cnx.create_aggregate("GROUP_CONCAT", 1, concat_strings)
   262     cnx.create_aggregate("GROUP_CONCAT", 1, concat_strings)
   257     
   263 
   258     def _limit_size(text, maxsize, format='text/plain'):
   264     def _limit_size(text, maxsize, format='text/plain'):
   259         if len(text) < maxsize:
   265         if len(text) < maxsize:
   260             return text
   266             return text
   261         if format in ('text/html', 'text/xhtml', 'text/xml'):
   267         if format in ('text/html', 'text/xhtml', 'text/xml'):
   262             text = remove_html_tags(text)
   268             text = remove_html_tags(text)