many optimizations in LAZY_TABLES, passes all tests, thanks Bruno
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.00.0 (2012-08-17 18:57:16) dev
|
Version 2.00.0 (2012-08-17 20:59:44) dev
|
||||||
|
|||||||
+57
-82
@@ -174,7 +174,7 @@ import platform
|
|||||||
CALLABLETYPES = (types.LambdaType, types.FunctionType,
|
CALLABLETYPES = (types.LambdaType, types.FunctionType,
|
||||||
types.BuiltinFunctionType,
|
types.BuiltinFunctionType,
|
||||||
types.MethodType, types.BuiltinMethodType)
|
types.MethodType, types.BuiltinMethodType)
|
||||||
|
TABLE_ARGS = ('migrate','primarykey','fake_migrate','format','singular','plural','trigger_name','sequence_name','common_filter','polymodel','table_class')
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
# following checks allow the use of dal without web2py, as a standalone module
|
# following checks allow the use of dal without web2py, as a standalone module
|
||||||
@@ -664,10 +664,10 @@ class BaseAdapter(ConnectionPool):
|
|||||||
constraint_name = self.constraint_name(tablename, field.name)
|
constraint_name = self.constraint_name(tablename, field.name)
|
||||||
if not '.' in referenced \
|
if not '.' in referenced \
|
||||||
and referenced != tablename \
|
and referenced != tablename \
|
||||||
and hasattr(table,'_primarykey'):
|
and table._primarykey:
|
||||||
ftype = self.types['integer']
|
ftype = self.types['integer']
|
||||||
else:
|
else:
|
||||||
if hasattr(table,'_primarykey'):
|
if table._primarykey:
|
||||||
rtablename,rfieldname = referenced.split('.')
|
rtablename,rfieldname = referenced.split('.')
|
||||||
rtable = table._db[rtablename]
|
rtable = table._db[rtablename]
|
||||||
rfield = rtable[rfieldname]
|
rfield = rtable[rfieldname]
|
||||||
@@ -783,7 +783,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
foreign_key = ', '.join(pkeys),
|
foreign_key = ', '.join(pkeys),
|
||||||
on_delete_action = field.ondelete)
|
on_delete_action = field.ondelete)
|
||||||
|
|
||||||
if hasattr(table,'_primarykey'):
|
if table._primarykey:
|
||||||
query = "CREATE TABLE %s(\n %s,\n %s) %s" % \
|
query = "CREATE TABLE %s(\n %s,\n %s) %s" % \
|
||||||
(tablename, fields,
|
(tablename, fields,
|
||||||
self.PRIMARY_KEY(', '.join(table._primarykey)),other)
|
self.PRIMARY_KEY(', '.join(table._primarykey)),other)
|
||||||
@@ -1053,7 +1053,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
if isinstance(e,self.integrity_error_class()):
|
if isinstance(e,self.integrity_error_class()):
|
||||||
return None
|
return None
|
||||||
raise e
|
raise e
|
||||||
if hasattr(table,'_primarykey'):
|
if table._primarykey:
|
||||||
return dict([(k[0].name, k[1]) for k in fields \
|
return dict([(k[0].name, k[1]) for k in fields \
|
||||||
if k[0].name in table._primarykey])
|
if k[0].name in table._primarykey])
|
||||||
id = self.lastrowid(table)
|
id = self.lastrowid(table)
|
||||||
@@ -1449,7 +1449,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
sql_o += ' ORDER BY %s' % self.expand(orderby)
|
sql_o += ' ORDER BY %s' % self.expand(orderby)
|
||||||
if limitby:
|
if limitby:
|
||||||
if not orderby and tablenames:
|
if not orderby and tablenames:
|
||||||
sql_o += ' ORDER BY %s' % ', '.join(['%s.%s'%(t,x) for t in tablenames for x in ((hasattr(self.db[t], '_primarykey') and self.db[t]._primarykey) or [self.db[t]._id.name])])
|
sql_o += ' ORDER BY %s' % ', '.join(['%s.%s'%(t,x) for t in tablenames for x in (self.db[t]._primarykey or [self.db[t]._id.name])])
|
||||||
# oracle does not support limitby
|
# oracle does not support limitby
|
||||||
sql = self.select_limitby(sql_s, sql_f, sql_t, sql_w, sql_o, limitby)
|
sql = self.select_limitby(sql_s, sql_f, sql_t, sql_w, sql_o, limitby)
|
||||||
if for_update and self.can_select_for_update is True:
|
if for_update and self.can_select_for_update is True:
|
||||||
@@ -3583,7 +3583,7 @@ class IngresAdapter(BaseAdapter):
|
|||||||
# post create table auto inc code (if needed)
|
# post create table auto inc code (if needed)
|
||||||
# modify table to btree for performance....
|
# modify table to btree for performance....
|
||||||
# Older Ingres releases could use rule/trigger like Oracle above.
|
# Older Ingres releases could use rule/trigger like Oracle above.
|
||||||
if hasattr(table,'_primarykey'):
|
if table._primarykey:
|
||||||
modify_tbl_sql = 'modify %s to btree unique on %s' % \
|
modify_tbl_sql = 'modify %s to btree unique on %s' % \
|
||||||
(table._tablename,
|
(table._tablename,
|
||||||
', '.join(["'%s'" % x for x in table.primarykey]))
|
', '.join(["'%s'" % x for x in table.primarykey]))
|
||||||
@@ -6576,7 +6576,7 @@ class DAL(dict):
|
|||||||
self._bigint_id = bigint_id
|
self._bigint_id = bigint_id
|
||||||
self._debug = debug
|
self._debug = debug
|
||||||
self._migrated = []
|
self._migrated = []
|
||||||
self._LAZY = {}
|
self._LAZY_TABLES = {}
|
||||||
self._lazy_tables = lazy_tables
|
self._lazy_tables = lazy_tables
|
||||||
if not str(attempts).isdigit() or attempts < 0:
|
if not str(attempts).isdigit() or attempts < 0:
|
||||||
attempts = 5
|
attempts = 5
|
||||||
@@ -6908,105 +6908,76 @@ def index():
|
|||||||
tablename,
|
tablename,
|
||||||
*fields,
|
*fields,
|
||||||
**args
|
**args
|
||||||
):
|
):
|
||||||
if tablename.startswith('_') or hasattr(self,tablename) or \
|
if not isinstance(tablename,str):
|
||||||
|
raise SyntaxError, "missing table name"
|
||||||
|
elif tablename.startswith('_') or hasattr(self,tablename) or \
|
||||||
regex_python_keywords.match(tablename):
|
regex_python_keywords.match(tablename):
|
||||||
raise SyntaxError, 'invalid table name: %s' % tablename
|
raise SyntaxError, 'invalid table name: %s' % tablename
|
||||||
elif tablename in self.tables:
|
elif tablename in self.tables:
|
||||||
raise SyntaxError, 'table already defined: %s' % tablename
|
raise SyntaxError, 'table already defined: %s' % tablename
|
||||||
elif self.check_reserved:
|
elif self.check_reserved:
|
||||||
self.check_reserved_keyword(tablename)
|
self.check_reserved_keyword(tablename)
|
||||||
|
|
||||||
if self._lazy_tables and not tablename in self._LAZY:
|
|
||||||
self._LAZY[tablename] = (fields,args)
|
|
||||||
self.tables.append(tablename)
|
|
||||||
else:
|
else:
|
||||||
t = self._define_table(tablename,*fields,**args)
|
invalid_args = [key for key in args if not key in TABLE_ARGS]
|
||||||
self.tables.append(tablename)
|
if invalid_args:
|
||||||
return t
|
raise SyntaxError, 'invalid table "%s" attributes: %s' \
|
||||||
|
% (tablename,invalid_args)
|
||||||
|
if self._lazy_tables and not tablename in self._LAZY_TABLES:
|
||||||
|
self._LAZY_TABLES[tablename] = (tablename,fields,args)
|
||||||
|
table = None
|
||||||
|
else:
|
||||||
|
table = self.lazy_define_table(tablename,*fields,**args)
|
||||||
|
self.tables.append(tablename)
|
||||||
|
return table
|
||||||
|
|
||||||
def _define_table(
|
def lazy_define_table(
|
||||||
self,
|
self,
|
||||||
tablename,
|
tablename,
|
||||||
*fields,
|
*fields,
|
||||||
**args
|
**args
|
||||||
):
|
):
|
||||||
|
|
||||||
for key in args:
|
|
||||||
if key not in [
|
|
||||||
'migrate',
|
|
||||||
'primarykey',
|
|
||||||
'fake_migrate',
|
|
||||||
'format',
|
|
||||||
'singular',
|
|
||||||
'plural',
|
|
||||||
'trigger_name',
|
|
||||||
'sequence_name',
|
|
||||||
'common_filter',
|
|
||||||
'polymodel',
|
|
||||||
'table_class']:
|
|
||||||
raise SyntaxError, 'invalid table "%s" attribute: %s' \
|
|
||||||
% (tablename, key)
|
|
||||||
if not isinstance(tablename,str):
|
|
||||||
raise SyntaxError, "missing table name"
|
|
||||||
tablename = cleanup(tablename)
|
|
||||||
migrate = self._migrate_enabled and args.get('migrate',
|
|
||||||
self._migrate)
|
|
||||||
fake_migrate = self._fake_migrate_all or args.get('fake_migrate',
|
|
||||||
self._fake_migrate)
|
|
||||||
table_class = args.get('table_class',Table)
|
|
||||||
format = args.get('format',None)
|
|
||||||
trigger_name = args.get('trigger_name', None)
|
|
||||||
sequence_name = args.get('sequence_name', None)
|
|
||||||
primarykey =args.get('primarykey',None)
|
|
||||||
polymodel = args.get('polymodel',None)
|
|
||||||
singular = args.get('singular',tablename.replace('_',' ').capitalize())
|
|
||||||
plural = args.get('plural',pluralize(singular.lower()).capitalize())
|
|
||||||
lowertablename = tablename.lower()
|
|
||||||
|
|
||||||
if self._common_fields:
|
if self._common_fields:
|
||||||
fields = [f for f in fields] + [f for f in self._common_fields]
|
fields = fields + self._common_fields
|
||||||
|
|
||||||
common_filter = args.get('common_filter', None)
|
|
||||||
|
|
||||||
t = self[tablename] = table_class(self, tablename, *fields,
|
|
||||||
**dict(primarykey=primarykey,
|
|
||||||
trigger_name=trigger_name,
|
|
||||||
sequence_name=sequence_name,
|
|
||||||
common_filter=common_filter))
|
|
||||||
|
|
||||||
|
table_class = args.get('table_class',Table)
|
||||||
|
table = table_class(self, tablename, *fields, **args)
|
||||||
|
table._actual = True
|
||||||
|
self[tablename] = table
|
||||||
|
|
||||||
# db magic
|
# db magic
|
||||||
if self._uri in (None,'None'):
|
if self._uri in (None,'None'):
|
||||||
return t
|
return table
|
||||||
|
|
||||||
t._create_references()
|
table._create_references()
|
||||||
|
|
||||||
|
migrate = self._migrate_enabled and args.get(
|
||||||
|
'migrate',self._migrate)
|
||||||
if migrate or self._adapter.dbengine=='google:datastore':
|
if migrate or self._adapter.dbengine=='google:datastore':
|
||||||
|
fake_migrate = self._fake_migrate_all or args.get(
|
||||||
|
'fake_migrate',self._fake_migrate)
|
||||||
|
polymodel = args.get('polymodel',None)
|
||||||
try:
|
try:
|
||||||
sql_locker.acquire()
|
sql_locker.acquire()
|
||||||
self._adapter.create_table(t,migrate=migrate,
|
self._adapter.create_table(table,migrate=migrate,
|
||||||
fake_migrate=fake_migrate,
|
fake_migrate=fake_migrate,
|
||||||
polymodel=polymodel)
|
polymodel=polymodel)
|
||||||
finally:
|
finally:
|
||||||
sql_locker.release()
|
sql_locker.release()
|
||||||
else:
|
else:
|
||||||
t._dbt = None
|
table._dbt = None
|
||||||
t._format = format
|
return table
|
||||||
t._singular = singular
|
|
||||||
t._plural = plural
|
|
||||||
t._actual = True
|
|
||||||
return t
|
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for tablename in self.tables:
|
for tablename in self.tables:
|
||||||
yield self[tablename]
|
yield self[tablename]
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
tablename = str(key)
|
key = str(key)
|
||||||
if not tablename is '_LAZY' and tablename in self._LAZY:
|
if not key is '_LAZY_TABLES' and key in self._LAZY_TABLES:
|
||||||
fields, args = self._LAZY.pop(tablename)
|
tablename, fields, args = self._LAZY_TABLES.pop(key)
|
||||||
return self._define_table(tablename,*fields,**args)
|
return self.lazy_define_table(tablename,*fields,**args)
|
||||||
return dict.__getitem__(self, tablename)
|
return dict.__getitem__(self, key)
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
dict.__setitem__(self, str(key), value)
|
dict.__setitem__(self, str(key), value)
|
||||||
@@ -7228,6 +7199,12 @@ class Table(dict):
|
|||||||
self._trigger_name = args.get('trigger_name',None) or \
|
self._trigger_name = args.get('trigger_name',None) or \
|
||||||
db and db._adapter.trigger_name(tablename)
|
db and db._adapter.trigger_name(tablename)
|
||||||
self._common_filter = args.get('common_filter', None)
|
self._common_filter = args.get('common_filter', None)
|
||||||
|
self._format = args.get('format',None)
|
||||||
|
self._singular = args.get(
|
||||||
|
'singular',tablename.replace('_',' ').capitalize())
|
||||||
|
self._plural = args.get(
|
||||||
|
'plural',pluralize(self._singular.lower()).capitalize())
|
||||||
|
self._primarykey = args.get('primarykey', None)
|
||||||
|
|
||||||
self._before_insert = []
|
self._before_insert = []
|
||||||
self._before_update = [lambda self,fs:self.delete_uploaded_files(fs)]
|
self._before_update = [lambda self,fs:self.delete_uploaded_files(fs)]
|
||||||
@@ -7236,17 +7213,15 @@ class Table(dict):
|
|||||||
self._after_update = []
|
self._after_update = []
|
||||||
self._after_delete = []
|
self._after_delete = []
|
||||||
|
|
||||||
primarykey = args.get('primarykey', None)
|
|
||||||
fieldnames,newfields=set(),[]
|
fieldnames,newfields=set(),[]
|
||||||
if primarykey:
|
if self._primarykey:
|
||||||
if not isinstance(primarykey,list):
|
if not isinstance(self._primarykey,list):
|
||||||
raise SyntaxError, \
|
raise SyntaxError, \
|
||||||
"primarykey must be a list of fields from table '%s'" \
|
"primarykey must be a list of fields from table '%s'" \
|
||||||
% tablename
|
% tablename
|
||||||
self._primarykey = primarykey
|
if len(self._primarykey)==1:
|
||||||
if len(primarykey)==1:
|
|
||||||
self._id = [f for f in fields if isinstance(f,Field) \
|
self._id = [f for f in fields if isinstance(f,Field) \
|
||||||
and f.name==primarykey[0]][0]
|
and f.name==self._primarykey[0]][0]
|
||||||
elif not [f for f in fields if isinstance(f,Field) and f.type=='id']:
|
elif not [f for f in fields if isinstance(f,Field) and f.type=='id']:
|
||||||
field = Field('id', 'id')
|
field = Field('id', 'id')
|
||||||
newfields.append(field)
|
newfields.append(field)
|
||||||
@@ -7318,7 +7293,7 @@ class Table(dict):
|
|||||||
field.requires = sqlhtml_validators(field)
|
field.requires = sqlhtml_validators(field)
|
||||||
self.ALL = SQLALL(self)
|
self.ALL = SQLALL(self)
|
||||||
|
|
||||||
if hasattr(self,'_primarykey'):
|
if self._primarykey:
|
||||||
for k in self._primarykey:
|
for k in self._primarykey:
|
||||||
if k not in self.fields:
|
if k not in self.fields:
|
||||||
raise SyntaxError, \
|
raise SyntaxError, \
|
||||||
@@ -7385,7 +7360,7 @@ class Table(dict):
|
|||||||
rtable = self._db[rtablename]
|
rtable = self._db[rtablename]
|
||||||
if len(refs)==2:
|
if len(refs)==2:
|
||||||
rfieldname = refs[1]
|
rfieldname = refs[1]
|
||||||
if not hasattr(rtable,'_primarykey'):
|
if not rtable._primarykey:
|
||||||
raise SyntaxError,\
|
raise SyntaxError,\
|
||||||
'keyed tables can only reference other keyed tables (for now)'
|
'keyed tables can only reference other keyed tables (for now)'
|
||||||
if rfieldname not in rtable.fields:
|
if rfieldname not in rtable.fields:
|
||||||
|
|||||||
+4
-4
@@ -842,7 +842,7 @@ class SQLFORM(FORM):
|
|||||||
nbsp = XML(' ') # Firefox2 does not display fields with blanks
|
nbsp = XML(' ') # Firefox2 does not display fields with blanks
|
||||||
FORM.__init__(self, *[], **attributes)
|
FORM.__init__(self, *[], **attributes)
|
||||||
ofields = fields
|
ofields = fields
|
||||||
keyed = hasattr(table,'_primarykey')
|
keyed = table._primarykey
|
||||||
|
|
||||||
# if no fields are provided, build it from the provided table
|
# if no fields are provided, build it from the provided table
|
||||||
# will only use writable or readable fields, unless forced to ignore
|
# will only use writable or readable fields, unless forced to ignore
|
||||||
@@ -1132,7 +1132,7 @@ class SQLFORM(FORM):
|
|||||||
if request_vars.__class__.__name__ == 'Request':
|
if request_vars.__class__.__name__ == 'Request':
|
||||||
request_vars = request_vars.post_vars
|
request_vars = request_vars.post_vars
|
||||||
|
|
||||||
keyed = hasattr(self.table, '_primarykey')
|
keyed = self.table._primarykey
|
||||||
|
|
||||||
# implement logic to detect whether record exist but has been modified
|
# implement logic to detect whether record exist but has been modified
|
||||||
# server side
|
# server side
|
||||||
@@ -2432,12 +2432,12 @@ class SQLTABLE(TABLE):
|
|||||||
href = '%s/%s/%s' % (linkto, ref, r_old)
|
href = '%s/%s/%s' % (linkto, ref, r_old)
|
||||||
if ref.find('.') >= 0:
|
if ref.find('.') >= 0:
|
||||||
tref,fref = ref.split('.')
|
tref,fref = ref.split('.')
|
||||||
if hasattr(sqlrows.db[tref],'_primarykey'):
|
if sqlrows.db[tref]._primarykey:
|
||||||
href = '%s/%s?%s' % (linkto, tref, urllib.urlencode({fref:r}))
|
href = '%s/%s?%s' % (linkto, tref, urllib.urlencode({fref:r}))
|
||||||
r = A(represent(field,r,record), _href=str(href))
|
r = A(represent(field,r,record), _href=str(href))
|
||||||
elif field.represent:
|
elif field.represent:
|
||||||
r = represent(field,r,record)
|
r = represent(field,r,record)
|
||||||
elif linkto and hasattr(field._table,'_primarykey') and fieldname in field._table._primarykey:
|
elif linkto and fieldname in field._table._primarykey:
|
||||||
# have to test this with multi-key tables
|
# have to test this with multi-key tables
|
||||||
key = urllib.urlencode(dict( [ \
|
key = urllib.urlencode(dict( [ \
|
||||||
((tablename in record \
|
((tablename in record \
|
||||||
|
|||||||
Reference in New Issue
Block a user