server/schema2sql.py
author Julien Cristau <julien.cristau@logilab.fr>
Thu, 15 Jan 2015 16:39:35 +0100
changeset 10199 218c28bff695
child 10201 989bbadbcd8d
permissions -rw-r--r--
Steal schema2sql module from yams It has no user inside yams, and we need it here if we want to be able to reference the (cubicweb-only) entities table from other tables. Related to #4846892
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10199
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     1
# copyright 2004-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     3
#
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     4
# This file is part of yams.
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     5
#
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     6
# yams is free software: you can redistribute it and/or modify it under the
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
     9
# any later version.
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    10
#
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    11
# yams is distributed in the hope that it will be useful, but WITHOUT ANY
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    12
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    13
# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    14
# details.
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    15
#
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    17
# with yams. If not, see <http://www.gnu.org/licenses/>.
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    18
"""write a schema as sql"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    19
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    20
__docformat__ = "restructuredtext en"
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    21
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    22
from hashlib import md5
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    23
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    24
from six.moves import range
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    25
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    26
from yams.constraints import SizeConstraint, UniqueConstraint
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    27
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    28
# default are usually not handled at the sql level. If you want them, set
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    29
# SET_DEFAULT to True
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    30
SET_DEFAULT = False
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    31
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    32
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    33
def schema2sql(dbhelper, schema, skip_entities=(), skip_relations=(), prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    34
    """write to the output stream a SQL schema to store the objects
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    35
    corresponding to the given schema
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    36
    """
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    37
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    38
    w = output.append
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    39
    for etype in sorted(schema.entities()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    40
        eschema = schema.eschema(etype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    41
        if eschema.final or eschema.type in skip_entities:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    42
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    43
        w(eschema2sql(dbhelper, eschema, skip_relations, prefix=prefix))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    44
    for rtype in sorted(schema.relations()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    45
        rschema = schema.rschema(rtype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    46
        if rschema.final or rschema.inlined or rschema.rule:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    47
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    48
        w(rschema2sql(rschema))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    49
    return '\n'.join(output)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    50
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    51
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    52
def dropschema2sql(dbhelper, schema, skip_entities=(), skip_relations=(), prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    53
    """write to the output stream a SQL schema to store the objects
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    54
    corresponding to the given schema
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    55
    """
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    56
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    57
    w = output.append
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    58
    for etype in sorted(schema.entities()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    59
        eschema = schema.eschema(etype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    60
        if eschema.final or eschema.type in skip_entities:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    61
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    62
        stmts = dropeschema2sql(dbhelper, eschema, skip_relations, prefix=prefix)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    63
        for stmt in stmts:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    64
            w(stmt)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    65
    for rtype in sorted(schema.relations()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    66
        rschema = schema.rschema(rtype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    67
        if rschema.final or rschema.inlined:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    68
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    69
        w(droprschema2sql(rschema))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    70
    return '\n'.join(output)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    71
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    72
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    73
def eschema_attrs(eschema, skip_relations):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    74
    attrs = [attrdef for attrdef in eschema.attribute_definitions()
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    75
             if not attrdef[0].type in skip_relations]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    76
    attrs += [(rschema, None)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    77
              for rschema in eschema.subject_relations()
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    78
              if not rschema.final and rschema.inlined]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    79
    return attrs
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    80
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    81
def unique_index_name(eschema, columns):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    82
    return u'unique_%s' % md5((eschema.type +
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    83
                              ',' +
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    84
                              ','.join(sorted(columns))).encode('ascii')).hexdigest()
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    85
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    86
def iter_unique_index_names(eschema):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    87
    for columns in eschema._unique_together or ():
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    88
        yield columns, unique_index_name(eschema, columns)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    89
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    90
def dropeschema2sql(dbhelper, eschema, skip_relations=(), prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    91
    """return sql to drop an entity type's table"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    92
    # not necessary to drop indexes, that's implictly done when
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    93
    # dropping the table, but we need to drop SQLServer views used to
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    94
    # create multicol unique indices
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    95
    statements = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    96
    tablename = prefix + eschema.type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    97
    if eschema._unique_together is not None:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    98
        for columns, index_name in iter_unique_index_names(eschema):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
    99
            cols  = ['%s%s' % (prefix, col) for col in columns]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   100
            sqls = dbhelper.sqls_drop_multicol_unique_index(tablename, cols, index_name)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   101
            statements += sqls
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   102
    statements += ['DROP TABLE %s;' % (tablename)]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   103
    return statements
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   104
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   105
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   106
def eschema2sql(dbhelper, eschema, skip_relations=(), prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   107
    """write an entity schema as SQL statements to stdout"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   108
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   109
    w = output.append
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   110
    table = prefix + eschema.type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   111
    w('CREATE TABLE %s(' % (table))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   112
    attrs = eschema_attrs(eschema, skip_relations)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   113
    # XXX handle objectinline physical mode
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   114
    for i in range(len(attrs)):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   115
        rschema, attrschema = attrs[i]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   116
        if attrschema is not None:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   117
            sqltype = aschema2sql(dbhelper, eschema, rschema, attrschema,
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   118
                                  indent=' ')
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   119
        else: # inline relation
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   120
            # XXX integer is ginco specific
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   121
            sqltype = 'integer'
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   122
        if i == len(attrs) - 1:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   123
            w(' %s%s %s' % (prefix, rschema.type, sqltype))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   124
        else:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   125
            w(' %s%s %s,' % (prefix, rschema.type, sqltype))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   126
    w(');')
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   127
    # create indexes
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   128
    for i in range(len(attrs)):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   129
        rschema, attrschema = attrs[i]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   130
        if attrschema is None or eschema.rdef(rschema).indexed:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   131
            w(dbhelper.sql_create_index(table, prefix + rschema.type))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   132
    for columns, index_name in iter_unique_index_names(eschema):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   133
        cols  = ['%s%s' % (prefix, col) for col in columns]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   134
        sqls = dbhelper.sqls_create_multicol_unique_index(table, cols, index_name)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   135
        for sql in sqls:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   136
            w(sql)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   137
    w('')
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   138
    return '\n'.join(output)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   139
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   140
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   141
def aschema2sql(dbhelper, eschema, rschema, aschema, creating=True, indent=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   142
    """write an attribute schema as SQL statements to stdout"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   143
    attr = rschema.type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   144
    rdef = rschema.rdef(eschema.type, aschema.type)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   145
    sqltype = type_from_constraints(dbhelper, aschema.type, rdef.constraints,
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   146
                                    creating)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   147
    if SET_DEFAULT:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   148
        default = eschema.default(attr)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   149
        if default is not None:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   150
            if aschema.type == 'Boolean':
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   151
                sqltype += ' DEFAULT %s' % dbhelper.boolean_value(default)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   152
            elif aschema.type == 'String':
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   153
                sqltype += ' DEFAULT %r' % str(default)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   154
            elif aschema.type in ('Int', 'BigInt', 'Float'):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   155
                sqltype += ' DEFAULT %s' % default
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   156
            # XXX ignore default for other type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   157
            # this is expected for NOW / TODAY
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   158
    if creating:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   159
        if rdef.uid:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   160
            sqltype += ' PRIMARY KEY'
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   161
        elif rdef.cardinality[0] == '1':
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   162
            # don't set NOT NULL if backend isn't able to change it later
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   163
            if dbhelper.alter_column_support:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   164
                sqltype += ' NOT NULL'
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   165
    # else we're getting sql type to alter a column, we don't want key / indexes
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   166
    # / null modifiers
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   167
    return sqltype
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   168
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   169
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   170
def type_from_constraints(dbhelper, etype, constraints, creating=True):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   171
    """return a sql type string corresponding to the constraints"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   172
    constraints = list(constraints)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   173
    unique, sqltype = False, None
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   174
    size_constrained_string = dbhelper.TYPE_MAPPING.get('SizeConstrainedString', 'varchar(%s)')
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   175
    if etype == 'String':
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   176
        for constraint in constraints:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   177
            if isinstance(constraint, SizeConstraint):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   178
                if constraint.max is not None:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   179
                    sqltype = size_constrained_string % constraint.max
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   180
            elif isinstance(constraint, UniqueConstraint):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   181
                unique = True
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   182
    if sqltype is None:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   183
        sqltype = dbhelper.TYPE_MAPPING[etype]
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   184
    if creating and unique:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   185
        sqltype += ' UNIQUE'
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   186
    return sqltype
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   187
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   188
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   189
_SQL_SCHEMA = """
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   190
CREATE TABLE %(table)s (
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   191
  eid_from INTEGER NOT NULL,
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   192
  eid_to INTEGER NOT NULL,
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   193
  CONSTRAINT %(table)s_p_key PRIMARY KEY(eid_from, eid_to)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   194
);
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   195
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   196
CREATE INDEX %(table)s_from_idx ON %(table)s(eid_from);
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   197
CREATE INDEX %(table)s_to_idx ON %(table)s(eid_to);"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   198
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   199
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   200
def rschema2sql(rschema):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   201
    assert not rschema.rule
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   202
    return _SQL_SCHEMA % {'table': '%s_relation' % rschema.type}
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   203
    
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   204
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   205
def droprschema2sql(rschema):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   206
    """return sql to drop a relation type's table"""
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   207
    # not necessary to drop indexes, that's implictly done when dropping
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   208
    # the table
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   209
    return 'DROP TABLE %s_relation;' % rschema.type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   210
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   211
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   212
def grant_schema(schema, user, set_owner=True, skip_entities=(), prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   213
    """write to the output stream a SQL schema to store the objects
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   214
    corresponding to the given schema
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   215
    """
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   216
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   217
    w = output.append
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   218
    for etype in sorted(schema.entities()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   219
        eschema = schema.eschema(etype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   220
        if eschema.final or etype in skip_entities:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   221
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   222
        w(grant_eschema(eschema, user, set_owner, prefix=prefix))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   223
    for rtype in sorted(schema.relations()):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   224
        rschema = schema.rschema(rtype)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   225
        if rschema.final or rschema.inlined:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   226
            continue
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   227
        w(grant_rschema(rschema, user, set_owner))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   228
    return '\n'.join(output)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   229
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   230
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   231
def grant_eschema(eschema, user, set_owner=True, prefix=''):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   232
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   233
    w = output.append
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   234
    etype = eschema.type
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   235
    if set_owner:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   236
        w('ALTER TABLE %s%s OWNER TO %s;' % (prefix, etype, user))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   237
    w('GRANT ALL ON %s%s TO %s;' % (prefix, etype, user))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   238
    return '\n'.join(output)
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   239
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   240
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   241
def grant_rschema(rschema, user, set_owner=True):
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   242
    output = []
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   243
    if set_owner:
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   244
        output.append('ALTER TABLE %s_relation OWNER TO %s;' % (rschema.type, user))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   245
    output.append('GRANT ALL ON %s_relation TO %s;' % (rschema.type, user))
218c28bff695 Steal schema2sql module from yams
Julien Cristau <julien.cristau@logilab.fr>
parents:
diff changeset
   246
    return '\n'.join(output)