127 if aschema is None: # inline relation |
128 if aschema is None: # inline relation |
128 continue |
129 continue |
129 attr = rschema.type |
130 attr = rschema.type |
130 rdef = rschema.rdef(eschema.type, aschema.type) |
131 rdef = rschema.rdef(eschema.type, aschema.type) |
131 for constraint in rdef.constraints: |
132 for constraint in rdef.constraints: |
132 cstrname, check = check_constraint(eschema, aschema, attr, constraint, prefix=prefix) |
133 cstrname, check = check_constraint(eschema, aschema, attr, constraint, dbhelper, prefix=prefix) |
133 if cstrname is not None: |
134 if cstrname is not None: |
134 w(', CONSTRAINT %s CHECK(%s)' % (cstrname, check)) |
135 w(', CONSTRAINT %s CHECK(%s)' % (cstrname, check)) |
135 w(');') |
136 w(');') |
136 # create indexes |
137 # create indexes |
137 for i in range(len(attrs)): |
138 for i in range(len(attrs)): |
144 for sql in sqls: |
145 for sql in sqls: |
145 w(sql) |
146 w(sql) |
146 w('') |
147 w('') |
147 return '\n'.join(output) |
148 return '\n'.join(output) |
148 |
149 |
149 def check_constraint(eschema, aschema, attr, constraint, prefix=''): |
150 def as_sql(value, dbhelper, prefix): |
|
151 if isinstance(value, Attribute): |
|
152 return prefix + value.attr |
|
153 elif isinstance(value, TODAY): |
|
154 return dbhelper.sql_current_date() |
|
155 elif isinstance(value, NOW): |
|
156 return dbhelper.sql_current_timestamp() |
|
157 else: |
|
158 # XXX more quoting for literals? |
|
159 return value |
|
160 |
|
161 def check_constraint(eschema, aschema, attr, constraint, dbhelper, prefix=''): |
150 # XXX should find a better name |
162 # XXX should find a better name |
151 cstrname = 'cstr' + md5(eschema.type + attr + constraint.type() + |
163 cstrname = 'cstr' + md5(eschema.type + attr + constraint.type() + |
152 (constraint.serialize() or '')).hexdigest() |
164 (constraint.serialize() or '')).hexdigest() |
153 if constraint.type() == 'BoundaryConstraint': |
165 if constraint.type() == 'BoundaryConstraint': |
154 if isinstance(constraint.boundary, Attribute): |
166 value = as_sql(constraint.boundary, dbhelper, prefix) |
155 value = prefix + constraint.boundary.attr |
|
156 else: |
|
157 value = constraint.boundary |
|
158 return cstrname, '%s%s %s %s' % (prefix, attr, constraint.operator, value) |
167 return cstrname, '%s%s %s %s' % (prefix, attr, constraint.operator, value) |
159 elif constraint.type() == 'IntervalBoundConstraint': |
168 elif constraint.type() == 'IntervalBoundConstraint': |
160 condition = [] |
169 condition = [] |
161 if constraint.minvalue is not None: |
170 if constraint.minvalue is not None: |
162 if isinstance(constraint.minvalue, Attribute): |
171 value = as_sql(constraint.minvalue, dbhelper, prefix) |
163 value = prefix + constraint.minvalue.attr |
|
164 else: |
|
165 value = constraint.minvalue |
|
166 condition.append('%s%s >= %s' % (prefix, attr, value)) |
172 condition.append('%s%s >= %s' % (prefix, attr, value)) |
167 if constraint.maxvalue is not None: |
173 if constraint.maxvalue is not None: |
168 if isinstance(constraint.maxvalue, Attribute): |
174 value = as_sql(constraint.maxvalue, dbhelper, prefix) |
169 value = prefix + constraint.maxvalue.attr |
|
170 else: |
|
171 value = constraint.maxvalue |
|
172 condition.append('%s%s <= %s' % (prefix, attr, value)) |
175 condition.append('%s%s <= %s' % (prefix, attr, value)) |
173 return cstrname, ' AND '.join(condition) |
176 return cstrname, ' AND '.join(condition) |
174 elif constraint.type() == 'StaticVocabularyConstraint': |
177 elif constraint.type() == 'StaticVocabularyConstraint': |
175 sample = next(iter(constraint.vocabulary())) |
178 sample = next(iter(constraint.vocabulary())) |
176 if not isinstance(sample, string_types): |
179 if not isinstance(sample, string_types): |