reverted to rname

This commit is contained in:
mdipierro
2013-10-20 16:48:22 -05:00
parent 4870b197de
commit 25148d06fe
3 changed files with 219 additions and 33 deletions
+1 -1
View File
@@ -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
View File
@@ -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)
+152
View File
@@ -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()