Updated from latest web2py master

This commit is contained in:
gi0baro committed 2014-09-19 17:37:35 +02:00
1 parent b20b81b8f5
commit 947dcbc226
6 files changed
+46 -20

No files matched your search

+15 -7
View File
@@ -64,7 +64,7 @@ class BaseAdapter(ConnectionPool):
__metaclass__ = AdapterMeta __metaclass__ = AdapterMeta
native_json = False driver_auto_json = False
driver = None driver = None
driver_name = None driver_name = None
drivers = () # list of drivers from which to pick drivers = () # list of drivers from which to pick
@@ -1113,13 +1113,20 @@ class BaseAdapter(ConnectionPool):
query = self.common_filter(query,tablenames_for_common_filters) query = self.common_filter(query,tablenames_for_common_filters)
sql_w = ' WHERE ' + self.expand(query) if query else '' sql_w = ' WHERE ' + self.expand(query) if query else ''
JOIN = ' CROSS JOIN '
if inner_join and not left: if inner_join and not left:
sql_t = ', '.join([self.table_alias(t) for t in iexcluded + \ # Wrap table references with parenthesis (approach 1)
itables_to_merge.keys()]) # sql_t = ', '.join([self.table_alias(t) for t in iexcluded + \
# itables_to_merge.keys()])
# sql_t = '(%s)' % sql_t
# or approach 2: Use 'JOIN' instead comma:
sql_t = JOIN.join([self.table_alias(t)
for t in iexcluded + itables_to_merge.keys()])
for t in ijoinon: for t in ijoinon:
sql_t += ' %s %s' % (icommand, t) sql_t += ' %s %s' % (icommand, t)
elif not inner_join and left: elif not inner_join and left:
sql_t = ', '.join([self.table_alias(t) for t in excluded + \ sql_t = JOIN.join([self.table_alias(t) for t in excluded + \
tables_to_merge.keys()]) tables_to_merge.keys()])
if joint: if joint:
sql_t += ' %s %s' % (command, sql_t += ' %s %s' % (command,
@@ -1133,7 +1140,7 @@ class BaseAdapter(ConnectionPool):
tables_in_joinon = set(joinont + ijoinont) tables_in_joinon = set(joinont + ijoinont)
tables_not_in_joinon = \ tables_not_in_joinon = \
all_tables_in_query.difference(tables_in_joinon) all_tables_in_query.difference(tables_in_joinon)
sql_t = ','.join([self.table_alias(t) for t in tables_not_in_joinon]) sql_t = JOIN.join([self.table_alias(t) for t in tables_not_in_joinon])
for t in ijoinon: for t in ijoinon:
sql_t += ' %s %s' % (icommand, t) sql_t += ' %s %s' % (icommand, t)
if joint: if joint:
@@ -1386,7 +1393,8 @@ class BaseAdapter(ConnectionPool):
else: else:
obj = str(obj) obj = str(obj)
elif fieldtype == 'json': elif fieldtype == 'json':
if not self.native_json: if not 'dumps' in self.driver_auto_json:
# always pass a string JSON string
if have_serializers: if have_serializers:
obj = serializers.json(obj) obj = serializers.json(obj)
elif simplejson: elif simplejson:
@@ -1524,7 +1532,7 @@ class BaseAdapter(ConnectionPool):
return float(value) return float(value)
def parse_json(self, value, field_type): def parse_json(self, value, field_type):
if not self.native_json: if not 'loads' in self.driver_auto_json:
if not isinstance(value, basestring): if not isinstance(value, basestring):
raise RuntimeError('json data not a string') raise RuntimeError('json data not a string')
if isinstance(value, unicode): if isinstance(value, unicode):
+13 -1
View File
@@ -5,7 +5,8 @@ import re
from .._compat import pjoin from .._compat import pjoin
from .._globals import IDENTITY, LOGGER, THREAD_LOCAL from .._globals import IDENTITY, LOGGER, THREAD_LOCAL
from .._load import classobj, gae, ndb, NDBDecimalProperty, GAEDecimalProperty, \ from .._load import classobj, gae, ndb, NDBDecimalProperty, GAEDecimalProperty, \
namespace_manager, Key, NDBPolyModel, PolyModel, rdbms namespace_manager, Key, NDBPolyModel, PolyModel, rdbms, have_serializers, \
serializers, simplejson
from ..objects import Table, Field, Expression, Query from ..objects import Table, Field, Expression, Query
from ..helpers.classes import SQLCustomType, SQLALL, Reference, UseDatabaseStoredFile from ..helpers.classes import SQLCustomType, SQLALL, Reference, UseDatabaseStoredFile
from ..helpers.methods import use_common_filters, xorify from ..helpers.methods import use_common_filters, xorify
@@ -173,6 +174,17 @@ class GoogleDatastoreAdapter(NoSQLAdapter):
def parse_id(self, value, field_type): def parse_id(self, value, field_type):
return value return value
def represent(self, obj, fieldtype):
if fieldtype == "json":
if have_serializers:
return serializers.json(obj)
elif simplejson:
return simplejson.dumps(obj)
else:
raise Exception("Could not dump json object (missing json library)")
else:
return NoSQLAdapter.represent(self, obj, fieldtype)
def create_table(self,table,migrate=True,fake_migrate=False, polymodel=None): def create_table(self,table,migrate=True,fake_migrate=False, polymodel=None):
myfields = {} myfields = {}
for field in table: for field in table:
+1 -1
View File
@@ -10,8 +10,8 @@ from ..helpers.methods import xorify
from .base import NoSQLAdapter from .base import NoSQLAdapter
class MongoDBAdapter(NoSQLAdapter): class MongoDBAdapter(NoSQLAdapter):
native_json = True
drivers = ('pymongo',) drivers = ('pymongo',)
driver_auto_json = ['loads','dumps']
uploads_in_blob = False uploads_in_blob = False
+10 -5
View File
@@ -175,16 +175,21 @@ class PostgreSQLAdapter(BaseAdapter):
# (to be added to after_connection) # (to be added to after_connection)
if self.driver_name == "pg8000": if self.driver_name == "pg8000":
supports_json = self.connection.server_version >= "9.2.0" supports_json = self.connection.server_version >= "9.2.0"
elif (self.driver_name == "psycopg2") and \ elif (self.driver_name == "psycopg2" and
(self.driver.__version__ >= "2.0.12"): self.driver.__version__ >= "2.0.12"):
supports_json = self.connection.server_version >= 90200 supports_json = self.connection.server_version >= 90200
elif self.driver_name == "zxJDBC": elif self.driver_name == "zxJDBC":
supports_json = self.connection.dbversion >= "9.2.0" supports_json = self.connection.dbversion >= "9.2.0"
else: supports_json = None else:
supports_json = None
if supports_json: if supports_json:
self.types["json"] = "JSON" self.types["json"] = "JSON"
self.native_json = True if (self.driver_name == "psycopg2" and
else: LOGGER.debug("Your database version does not support the JSON data type (using TEXT instead)") self.driver.__version__ >= '2.5.0'):
self.driver_auto_json = ['loads']
else:
LOGGER.debug("Your database version does not support the JSON"
" data type (using TEXT instead)")
def LIKE(self,first,second): def LIKE(self,first,second):
args = (self.expand(first), self.expand(second,'string')) args = (self.expand(first), self.expand(second,'string'))
+2 -2
View File
@@ -192,7 +192,7 @@ def smart_query(fields,text):
elif op == 'notbelongs': new_query = ~field.belongs(value.split(',')) elif op == 'notbelongs': new_query = ~field.belongs(value.split(','))
elif field.type in ('text', 'string', 'json'): elif field.type in ('text', 'string', 'json'):
if op == 'contains': new_query = field.contains(value) if op == 'contains': new_query = field.contains(value)
elif op == 'like': new_query = field.like(value) elif op == 'like': new_query = field.ilike(value)
elif op == 'startswith': new_query = field.startswith(value) elif op == 'startswith': new_query = field.startswith(value)
elif op == 'endswith': new_query = field.endswith(value) elif op == 'endswith': new_query = field.endswith(value)
else: raise RuntimeError("Invalid operation") else: raise RuntimeError("Invalid operation")
@@ -246,7 +246,7 @@ def sqlhtml_validators(field):
if field_type in (('string', 'text', 'password')): if field_type in (('string', 'text', 'password')):
requires.append(validators.IS_LENGTH(field_length)) requires.append(validators.IS_LENGTH(field_length))
elif field_type == 'json': elif field_type == 'json':
requires.append(validators.IS_EMPTY_OR(validators.IS_JSON(native_json=field.db._adapter.native_json))) requires.append(validators.IS_EMPTY_OR(validators.IS_JSON()))
elif field_type == 'double' or field_type == 'float': elif field_type == 'double' or field_type == 'float':
requires.append(validators.IS_FLOAT_IN_RANGE(-1e100, 1e100)) requires.append(validators.IS_FLOAT_IN_RANGE(-1e100, 1e100))
elif field_type == 'integer': elif field_type == 'integer':
+5 -4
View File
@@ -1207,6 +1207,9 @@ class Expression(object):
op = case_sensitive and db._adapter.LIKE or db._adapter.ILIKE op = case_sensitive and db._adapter.LIKE or db._adapter.ILIKE
return Query(db, op, self, value) return Query(db, op, self, value)
def ilike(self, value):
return self.like(case_sensitive=False)
def regexp(self, value): def regexp(self, value):
db = self.db db = self.db
return Query(db, db._adapter.REGEXP, self, value) return Query(db, db._adapter.REGEXP, self, value)
@@ -1254,14 +1257,12 @@ class Expression(object):
def contains(self, value, all=False, case_sensitive=False): def contains(self, value, all=False, case_sensitive=False):
""" """
The case_sensitive parameters is only useful for PostgreSQL
For other RDMBs it is ignored and contains is always case insensitive
For MongoDB and GAE contains is always case sensitive For MongoDB and GAE contains is always case sensitive
""" """
db = self.db db = self.db
if isinstance(value,(list, tuple)): if isinstance(value,(list, tuple)):
subqueries = [self.contains(str(v).strip(),case_sensitive=case_sensitive) subqueries = [self.contains(str(v),case_sensitive=case_sensitive)
for v in value if str(v).strip()] for v in value if str(v)]
if not subqueries: if not subqueries:
return self.contains('') return self.contains('')
else: else: