reverted to rname
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 2.7.4-stable+timestamp.2013.10.20.16.41.51
|
||||
Version 2.7.4-stable+timestamp.2013.10.20.15.42.03
|
||||
|
||||
+66
-32
@@ -195,7 +195,8 @@ CALLABLETYPES = (types.LambdaType, types.FunctionType,
|
||||
TABLE_ARGS = set(
|
||||
('migrate','primarykey','fake_migrate','format','redefine',
|
||||
'singular','plural','trigger_name','sequence_name','fields',
|
||||
'common_filter','polymodel','table_class','on_define','actual_name'))
|
||||
'common_filter','polymodel','table_class','on_define','actual_name',
|
||||
'rname'))
|
||||
|
||||
SELECT_ARGS = set(
|
||||
('orderby', 'groupby', 'limitby','required', 'cache', 'left',
|
||||
@@ -864,11 +865,12 @@ class BaseAdapter(ConnectionPool):
|
||||
id_fieldname = table._id.name
|
||||
else: #make a guess
|
||||
id_fieldname = 'id'
|
||||
real_referenced = db[referenced]._rname or db[referenced]
|
||||
ftype = types[field_type[:9]] % dict(
|
||||
index_name = field_name+'__idx',
|
||||
field_name = field_name,
|
||||
constraint_name = constraint_name,
|
||||
foreign_key = '%s (%s)' % (referenced,
|
||||
foreign_key = '%s (%s)' % (real_referenced,
|
||||
id_fieldname),
|
||||
on_delete_action=field.ondelete)
|
||||
elif field_type.startswith('list:reference'):
|
||||
@@ -965,13 +967,16 @@ class BaseAdapter(ConnectionPool):
|
||||
foreign_key = ', '.join(pkeys),
|
||||
on_delete_action = field.ondelete)
|
||||
|
||||
#if there's a _rname, let's use that instead
|
||||
table_rname = table._rname or tablename
|
||||
|
||||
if getattr(table,'_primarykey',None):
|
||||
query = "CREATE TABLE %s(\n %s,\n %s) %s" % \
|
||||
(tablename, fields,
|
||||
(table_rname, fields,
|
||||
self.PRIMARY_KEY(', '.join(table._primarykey)),other)
|
||||
else:
|
||||
query = "CREATE TABLE %s(\n %s\n)%s" % \
|
||||
(tablename, fields, other)
|
||||
(table_rname, fields, other)
|
||||
|
||||
if self.uri.startswith('sqlite:///') \
|
||||
or self.uri.startswith('spatialite:///'):
|
||||
@@ -1023,10 +1028,12 @@ class BaseAdapter(ConnectionPool):
|
||||
raise RuntimeError('File %s appears corrupted' % table._dbt)
|
||||
self.file_close(tfile)
|
||||
if sql_fields != sql_fields_old:
|
||||
self.migrate_table(table,
|
||||
sql_fields, sql_fields_old,
|
||||
sql_fields_aux, None,
|
||||
fake_migrate=fake_migrate)
|
||||
self.migrate_table(
|
||||
table,
|
||||
sql_fields, sql_fields_old,
|
||||
sql_fields_aux, None,
|
||||
fake_migrate=fake_migrate
|
||||
)
|
||||
return query
|
||||
|
||||
def migrate_table(
|
||||
@@ -1211,7 +1218,8 @@ class BaseAdapter(ConnectionPool):
|
||||
return 'PRIMARY KEY(%s)' % key
|
||||
|
||||
def _drop(self, table, mode):
|
||||
return ['DROP TABLE %s;' % table]
|
||||
table_rname = table._rname or table
|
||||
return ['DROP TABLE %s;' % table_rname]
|
||||
|
||||
def drop(self, table, mode=''):
|
||||
db = table._db
|
||||
@@ -1229,15 +1237,17 @@ class BaseAdapter(ConnectionPool):
|
||||
self.log('success!\n', table)
|
||||
|
||||
def _insert(self, table, fields):
|
||||
table_rname = table._rname or table
|
||||
if fields:
|
||||
keys = ','.join(f.name for f, v in fields)
|
||||
values = ','.join(self.expand(v, f.type) for f, v in fields)
|
||||
return 'INSERT INTO %s(%s) VALUES (%s);' % (table, keys, values)
|
||||
return 'INSERT INTO %s(%s) VALUES (%s);' % (table_rname, keys, values)
|
||||
else:
|
||||
return self._insert_empty(table)
|
||||
|
||||
def _insert_empty(self, table):
|
||||
return 'INSERT INTO %s DEFAULT VALUES;' % table
|
||||
table_rname = table._rname or table
|
||||
return 'INSERT INTO %s DEFAULT VALUES;' % table_rname
|
||||
|
||||
def insert(self, table, fields):
|
||||
query = self._insert(table,fields)
|
||||
@@ -1393,9 +1403,10 @@ class BaseAdapter(ConnectionPool):
|
||||
return '%s AS %s' % (self.expand(first), second)
|
||||
|
||||
def ON(self, first, second):
|
||||
table_rname = first._ot and first or first._rname or first._tablename
|
||||
if use_common_filters(second):
|
||||
second = self.common_filter(second,[first._tablename])
|
||||
return '%s ON %s' % (self.expand(first), self.expand(second))
|
||||
return '%s ON %s' % (self.expand(table_rname), self.expand(second))
|
||||
|
||||
def INVERT(self, first):
|
||||
return '%s DESC' % self.expand(first)
|
||||
@@ -1406,9 +1417,14 @@ class BaseAdapter(ConnectionPool):
|
||||
def CAST(self, first, second):
|
||||
return 'CAST(%s AS %s)' % (first, second)
|
||||
|
||||
def expand(self, expression, field_type=None):
|
||||
def expand(self, expression, field_type=None, colnames=False):
|
||||
if isinstance(expression, Field):
|
||||
out = '%s.%s' % (expression.table._tablename, expression.name)
|
||||
et = expression.table
|
||||
if not colnames:
|
||||
table_rname = et._ot and et._tablename or et._rname or et._tablename
|
||||
else:
|
||||
table_rname = et._tablename
|
||||
out = '%s.%s' % (table_rname, expression.name)
|
||||
if field_type == 'string' and not expression.type in (
|
||||
'string','text','json','password'):
|
||||
out = self.CAST(out, self.types['text'])
|
||||
@@ -1440,7 +1456,9 @@ class BaseAdapter(ConnectionPool):
|
||||
return str(expression)
|
||||
|
||||
def table_alias(self,name):
|
||||
return str(name if isinstance(name,Table) else self.db[name])
|
||||
if not isinstance(name, Table):
|
||||
name = self.db[name]._rname or self.db[name]
|
||||
return str(name)
|
||||
|
||||
def alias(self, table, alias):
|
||||
"""
|
||||
@@ -1448,7 +1466,7 @@ class BaseAdapter(ConnectionPool):
|
||||
with alias name.
|
||||
"""
|
||||
other = copy.copy(table)
|
||||
other['_ot'] = other._ot or other._tablename
|
||||
other['_ot'] = other._ot or other._rname or other._tablename
|
||||
other['ALL'] = SQLALL(other)
|
||||
other['_tablename'] = alias
|
||||
for fieldname in other.fields:
|
||||
@@ -1460,7 +1478,7 @@ class BaseAdapter(ConnectionPool):
|
||||
return other
|
||||
|
||||
def _truncate(self, table, mode=''):
|
||||
tablename = table._tablename
|
||||
tablename = table._rname or table._tablename
|
||||
return ['TRUNCATE TABLE %s %s;' % (tablename, mode or '')]
|
||||
|
||||
def truncate(self, table, mode= ' '):
|
||||
@@ -1485,7 +1503,7 @@ class BaseAdapter(ConnectionPool):
|
||||
sql_v = ','.join(['%s=%s' % (field.name,
|
||||
self.expand(value, field.type)) \
|
||||
for (field, value) in fields])
|
||||
tablename = "%s" % self.db[tablename]
|
||||
tablename = "%s" % (self.db[tablename]._rname or tablename)
|
||||
return 'UPDATE %s SET %s%s;' % (tablename, sql_v, sql_w)
|
||||
|
||||
def update(self, tablename, query, fields):
|
||||
@@ -1510,6 +1528,7 @@ class BaseAdapter(ConnectionPool):
|
||||
sql_w = ' WHERE ' + self.expand(query)
|
||||
else:
|
||||
sql_w = ''
|
||||
tablename = '%s' % (self.db[tablename]._rname or tablename)
|
||||
return 'DELETE FROM %s%s;' % (tablename, sql_w)
|
||||
|
||||
def delete(self, tablename, query):
|
||||
@@ -1583,7 +1602,9 @@ class BaseAdapter(ConnectionPool):
|
||||
|
||||
if len(tablenames) < 1:
|
||||
raise SyntaxError('Set: no tables selected')
|
||||
self._colnames = map(self.expand, fields)
|
||||
def colexpand(field):
|
||||
return self.expand(field, colnames=True)
|
||||
self._colnames = map(colexpand, fields)
|
||||
def geoexpand(field):
|
||||
if isinstance(field.type,str) and field.type.startswith('geometry'):
|
||||
field = field.st_astext()
|
||||
@@ -1692,7 +1713,13 @@ class BaseAdapter(ConnectionPool):
|
||||
else:
|
||||
sql_o += ' ORDER BY %s' % self.expand(orderby)
|
||||
if (limitby and not groupby and tablenames and orderby_on_limitby and not orderby):
|
||||
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 (
|
||||
hasattr(self.db[t],'_primarykey') and self.db[t]._primarykey
|
||||
or [self.db[t]._id.name]
|
||||
)
|
||||
]
|
||||
)
|
||||
# oracle does not support 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:
|
||||
@@ -2508,7 +2535,8 @@ class MySQLAdapter(BaseAdapter):
|
||||
|
||||
def _drop(self,table,mode):
|
||||
# breaks db integrity but without this mysql does not drop table
|
||||
return ['SET FOREIGN_KEY_CHECKS=0;','DROP TABLE %s;' % table,
|
||||
table_rname = table._rname or table
|
||||
return ['SET FOREIGN_KEY_CHECKS=0;','DROP TABLE %s;' % table_rname,
|
||||
'SET FOREIGN_KEY_CHECKS=1;']
|
||||
|
||||
def _insert_empty(self, table):
|
||||
@@ -2616,7 +2644,7 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
|
||||
}
|
||||
|
||||
QUOTE_TEMPLATE = '%s'
|
||||
QUOTE_TEMPLATE = '"%s"'
|
||||
|
||||
def varquote(self,name):
|
||||
return varquote_aux(name,'"%s"')
|
||||
@@ -2630,7 +2658,7 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
return "'%s'" % str(obj).replace("'","''")
|
||||
|
||||
def sequence_name(self,table):
|
||||
return '%s_id_Seq' % table
|
||||
return '%s_id_seq' % table
|
||||
|
||||
def RANDOM(self):
|
||||
return 'RANDOM()'
|
||||
@@ -2720,7 +2748,7 @@ class PostgreSQLAdapter(BaseAdapter):
|
||||
self.try_json()
|
||||
|
||||
def lastrowid(self,table):
|
||||
self.execute("select currval('%s')" % table._sequence_name)
|
||||
self.execute("""select currval('"%s"')""" % table._sequence_name)
|
||||
return int(self.cursor.fetchone()[0])
|
||||
|
||||
def try_json(self):
|
||||
@@ -3369,7 +3397,7 @@ class MSSQL3Adapter(MSSQLAdapter):
|
||||
|
||||
class MSSQL4Adapter(MSSQLAdapter):
|
||||
""" support for true pagination in MSSQL >= 2012"""
|
||||
|
||||
|
||||
def select_limitby(self, sql_s, sql_f, sql_t, sql_w, sql_o, limitby):
|
||||
if not sql_o:
|
||||
#if there is no orderby, we can't use the brand new statements
|
||||
@@ -3382,7 +3410,7 @@ class MSSQL4Adapter(MSSQLAdapter):
|
||||
(sql_s, sql_f, sql_t, sql_w, sql_o)
|
||||
|
||||
def rowslice(self,rows,minimum=0,maximum=None):
|
||||
return rows
|
||||
return rows
|
||||
|
||||
class MSSQL2Adapter(MSSQLAdapter):
|
||||
drivers = ('pyodbc',)
|
||||
@@ -6593,7 +6621,7 @@ class IMAPAdapter(NoSQLAdapter):
|
||||
else:
|
||||
message[item] = ";".join([i for i in
|
||||
value])
|
||||
if (not message.is_multipart() and
|
||||
if (not message.is_multipart() and
|
||||
(not message.get_content_type().startswith(
|
||||
"multipart"))):
|
||||
if isinstance(content, basestring):
|
||||
@@ -8357,8 +8385,14 @@ class Table(object):
|
||||
self._actual = False # set to True by define_table()
|
||||
self._tablename = tablename
|
||||
self._ot = args.get('actual_name')
|
||||
self._sequence_name = args.get('sequence_name') or \
|
||||
db and db._adapter.sequence_name(tablename)
|
||||
self._rname = args.get('rname')
|
||||
if not self._rname:
|
||||
self._sequence_name = args.get('sequence_name') or \
|
||||
db and db._adapter.sequence_name(tablename)
|
||||
else:
|
||||
tb = self._rname[1:-1]
|
||||
self._sequence_name = args.get('sequence_name') or \
|
||||
db and db._adapter.sequence_name(tb)
|
||||
self._trigger_name = args.get('trigger_name') or \
|
||||
db and db._adapter.trigger_name(tablename)
|
||||
self._common_filter = args.get('common_filter')
|
||||
@@ -8503,10 +8537,10 @@ class Table(object):
|
||||
clones.append(field.clone(
|
||||
unique=False, type=field.type if nfk else 'bigint'))
|
||||
archive_db.define_table(
|
||||
archive_name,
|
||||
archive_name,
|
||||
Field(current_record,field_type,label=current_record_label),
|
||||
*clones,**dict(format=self._format))
|
||||
|
||||
|
||||
self._before_update.append(
|
||||
lambda qset,fs,db=archive_db,an=archive_name,cn=current_record:
|
||||
archive_record(qset,fs,db[an],cn))
|
||||
@@ -8690,7 +8724,7 @@ class Table(object):
|
||||
|
||||
def __str__(self):
|
||||
if self._ot is not None:
|
||||
ot = self._db._adapter.QUOTE_TEMPLATE % self._ot
|
||||
ot = self._ot
|
||||
if 'Oracle' in str(type(self._db._adapter)):
|
||||
return '%s %s' % (ot, self._tablename)
|
||||
return '%s AS %s' % (ot, self._tablename)
|
||||
|
||||
@@ -836,6 +836,158 @@ class TestValidateAndInsert(unittest.TestCase):
|
||||
db.val_and_insert.drop()
|
||||
|
||||
|
||||
class TestZRName(unittest.TestCase):
|
||||
"""
|
||||
tests for highly experimental rname attribute
|
||||
"""
|
||||
def testSelect(self):
|
||||
db = DAL(DEFAULT_URI, check_reserved=['all'])
|
||||
rname = db._adapter.QUOTE_TEMPLATE % 'a very complicated tablename'
|
||||
db.define_table(
|
||||
'easy_name',
|
||||
Field('a_field'),
|
||||
rname=rname
|
||||
)
|
||||
rtn = db.easy_name.insert(a_field='a')
|
||||
self.assertEqual(rtn.id, 1)
|
||||
rtn = db(db.easy_name.a_field == 'a').select()
|
||||
self.assertEqual(len(rtn), 1)
|
||||
self.assertEqual(rtn[0].id, 1)
|
||||
self.assertEqual(rtn[0].a_field, 'a')
|
||||
db.easy_name.insert(a_field='b')
|
||||
rtn = db(db.easy_name.id > 0).delete()
|
||||
self.assertEqual(rtn, 2)
|
||||
rtn = db(db.easy_name.id > 0).count()
|
||||
self.assertEqual(rtn, 0)
|
||||
db.easy_name.insert(a_field='a')
|
||||
db.easy_name.insert(a_field='b')
|
||||
rtn = db(db.easy_name.id > 0).count()
|
||||
self.assertEqual(rtn, 2)
|
||||
rtn = db(db.easy_name.a_field == 'a').update(a_field='c')
|
||||
rtn = db(db.easy_name.a_field == 'c').count()
|
||||
self.assertEqual(rtn, 1)
|
||||
rtn = db(db.easy_name.a_field != 'c').count()
|
||||
self.assertEqual(rtn, 1)
|
||||
avg = db.easy_name.id.avg()
|
||||
rtn = db(db.easy_name.id > 0).select(avg)
|
||||
self.assertEqual(rtn[0][avg], 3)
|
||||
rname = db._adapter.QUOTE_TEMPLATE % 'this is the person table'
|
||||
db.define_table(
|
||||
'person',
|
||||
Field('name', default="Michael"),
|
||||
Field('uuid'),
|
||||
rname=rname
|
||||
)
|
||||
rname = db._adapter.QUOTE_TEMPLATE % 'this is the pet table'
|
||||
db.define_table(
|
||||
'pet',
|
||||
Field('friend','reference person'),
|
||||
Field('name'),
|
||||
rname=rname
|
||||
)
|
||||
michael = db.person.insert() #default insert
|
||||
john = db.person.insert(name='John')
|
||||
luke = db.person.insert(name='Luke')
|
||||
|
||||
#michael owns Phippo
|
||||
phippo = db.pet.insert(friend=michael, name="Phippo")
|
||||
#john owns Dunstin and Gertie
|
||||
dunstin = db.pet.insert(friend=john, name="Dunstin")
|
||||
gertie = db.pet.insert(friend=john, name="Gertie")
|
||||
|
||||
rtn = db(db.person.id == db.pet.friend).select(orderby=db.person.id|db.pet.id)
|
||||
self.assertEqual(len(rtn), 3)
|
||||
self.assertEqual(rtn[0].person.id, michael)
|
||||
self.assertEqual(rtn[0].person.name, 'Michael')
|
||||
self.assertEqual(rtn[0].pet.id, phippo)
|
||||
self.assertEqual(rtn[0].pet.name, 'Phippo')
|
||||
self.assertEqual(rtn[1].person.id, john)
|
||||
self.assertEqual(rtn[1].person.name, 'John')
|
||||
self.assertEqual(rtn[1].pet.name, 'Dunstin')
|
||||
self.assertEqual(rtn[2].pet.name, 'Gertie')
|
||||
#fetch owners, eventually with pet
|
||||
#main point is retrieving Luke with no pets
|
||||
rtn = db(db.person.id > 0).select(
|
||||
orderby=db.person.id|db.pet.id,
|
||||
left=db.pet.on(db.person.id == db.pet.friend)
|
||||
)
|
||||
self.assertEqual(rtn[0].person.id, michael)
|
||||
self.assertEqual(rtn[0].person.name, 'Michael')
|
||||
self.assertEqual(rtn[0].pet.id, phippo)
|
||||
self.assertEqual(rtn[0].pet.name, 'Phippo')
|
||||
self.assertEqual(rtn[3].person.name, 'Luke')
|
||||
self.assertEqual(rtn[3].person.id, luke)
|
||||
self.assertEqual(rtn[3].pet.name, None)
|
||||
#lets test a subquery
|
||||
subq = db(db.pet.name == "Gertie")._select(db.pet.friend)
|
||||
rtn = db(db.person.id.belongs(subq)).select()
|
||||
self.assertEqual(rtn[0].id, 2)
|
||||
self.assertEqual(rtn[0]('person.name'), 'John')
|
||||
#as dict
|
||||
rtn = db(db.person.id > 0).select().as_dict()
|
||||
self.assertEqual(rtn[1]['name'], 'Michael')
|
||||
#as list
|
||||
rtn = db(db.person.id > 0).select().as_list()
|
||||
self.assertEqual(rtn[0]['name'], 'Michael')
|
||||
#isempty
|
||||
rtn = db(db.person.id > 0).isempty()
|
||||
self.assertEqual(rtn, False)
|
||||
#join argument
|
||||
rtn = db(db.person).select(orderby=db.person.id|db.pet.id,
|
||||
join=db.pet.on(db.person.id==db.pet.friend))
|
||||
self.assertEqual(len(rtn), 3)
|
||||
self.assertEqual(rtn[0].person.id, michael)
|
||||
self.assertEqual(rtn[0].person.name, 'Michael')
|
||||
self.assertEqual(rtn[0].pet.id, phippo)
|
||||
self.assertEqual(rtn[0].pet.name, 'Phippo')
|
||||
self.assertEqual(rtn[1].person.id, john)
|
||||
self.assertEqual(rtn[1].person.name, 'John')
|
||||
self.assertEqual(rtn[1].pet.name, 'Dunstin')
|
||||
self.assertEqual(rtn[2].pet.name, 'Gertie')
|
||||
|
||||
#aliases
|
||||
rname = db._adapter.QUOTE_TEMPLATE % 'the cubs'
|
||||
db.define_table('pet_farm',
|
||||
Field('name'),
|
||||
Field('father','reference pet_farm'),
|
||||
Field('mother','reference pet_farm'),
|
||||
rname=rname
|
||||
)
|
||||
|
||||
minali = db.pet_farm.insert(name='Minali')
|
||||
osbert = db.pet_farm.insert(name='Osbert')
|
||||
#they had a cub
|
||||
selina = db.pet_farm.insert(name='Selina', father=osbert, mother=minali)
|
||||
|
||||
father = db.pet_farm.with_alias('father')
|
||||
mother = db.pet_farm.with_alias('mother')
|
||||
|
||||
#fetch pets with relatives
|
||||
rtn = db().select(
|
||||
db.pet_farm.name, father.name, mother.name,
|
||||
left=[
|
||||
father.on(father.id == db.pet_farm.father),
|
||||
mother.on(mother.id == db.pet_farm.mother)
|
||||
],
|
||||
orderby=db.pet_farm.id
|
||||
)
|
||||
|
||||
self.assertEqual(len(rtn), 3)
|
||||
self.assertEqual(rtn[0].pet_farm.name, 'Minali')
|
||||
self.assertEqual(rtn[0].father.name, None)
|
||||
self.assertEqual(rtn[0].mother.name, None)
|
||||
self.assertEqual(rtn[1].pet_farm.name, 'Osbert')
|
||||
self.assertEqual(rtn[2].pet_farm.name, 'Selina')
|
||||
self.assertEqual(rtn[2].father.name, 'Osbert')
|
||||
self.assertEqual(rtn[2].mother.name, 'Minali')
|
||||
|
||||
#clean up
|
||||
db.pet_farm.drop()
|
||||
db.pet.drop()
|
||||
db.person.drop()
|
||||
db.easy_name.drop()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user