示例#1
0
    def execute(self, q, args=()):
        """
        Send a query to the Salesforce API.
        """
        self.rowcount = None
        if isinstance(self.query, SalesforceQuery) or self.query is None:
            response = self.execute_select(q, args)
            #print("response : %s" % response.text)
        elif isinstance(self.query, SalesforceRawQuery):
            response = self.execute_select(q, args)
        elif isinstance(self.query, subqueries.InsertQuery):
            response = self.execute_insert(self.query)
        elif isinstance(self.query, subqueries.UpdateQuery):
            response = self.execute_update(self.query)
        elif isinstance(self.query, subqueries.DeleteQuery):
            response = self.execute_delete(self.query)
        else:
            raise DatabaseError("Unsupported query: type %s: %s" %
                                (type(self.query), self.query))

        if response and isinstance(response, list):
            # bulk operation SOAP
            if all(x['success'] for x in response):
                self.lastrowid = [item['id'] for item in response]
        # the encoding is detected automatically, e.g. from headers
        elif (response and response.text):
            # parse_float set to decimal.Decimal to avoid precision errors when
            # converting from the json number to a float to a Decimal object
            # on a model's DecimalField...converts from json number directly
            # a Decimal object
            data = response.json(parse_float=decimal.Decimal)
            # a SELECT query
            if ('totalSize' in data):
                self.rowcount = data['totalSize']
            # a successful INSERT query, return after getting PK
            elif ('success' in data and 'id' in data):
                self.lastrowid = data['id']
                return
            elif data['hasErrors'] == False:
                # save id from bulk_create even if Django don't use it
                if data['results'] and data['results'][0]['result']:
                    self.lastrowid = [
                        item['result']['id'] for item in data['results']
                    ]
                return
            # something we don't recognize
            else:
                raise DatabaseError(data)

            if q.upper().startswith('SELECT COUNT() FROM'):
                # COUNT() queries in SOQL are a special case, as they don't actually return rows
                self.results = iter([[self.rowcount]])
            else:
                if self.query:
                    self.query.first_chunk_len = len(data['records'])
                self.first_row = data['records'][0] if data['records'] else None
                self.results = self.query_results(data)
        else:
            self.results = iter([])
示例#2
0
 def __init__(self, message='', data=None, response=None, verbose=False):
     DatabaseError.__init__(self, message)
     self.data = data
     self.response = response
     self.verbose = verbose
     if verbose:
         log.info("Error (debug details) %s\n%s", response.text,
                  response.__dict__)
示例#3
0
	def __init__(self, message='', data=None, response=None, verbose=False):
		DatabaseError.__init__(self, message)
		self.data = data
		self.response = response
		self.verbose = verbose
		if verbose:
			log.info("Error (debug details) %s\n%s", response.text,
					response.__dict__)
示例#4
0
def reauthenticate(db_alias):
	if connections['salesforce'].sf_session.auth.dynamic_token is None:
		expire_token(db_alias)
		oauth = authenticate(db_alias=db_alias)
		return oauth['access_token']
	else:
		# It is expected that with dynamic authentication we get a token that
		# is valid at least for a few future seconds, because we don't get
		# any password or permanent permission for it from the user.
		raise DatabaseError("Dynamically authenticated connection can never reauthenticate.")
示例#5
0
 def reauthenticate(self):
     if self.dynamic is None:
         self.del_token()
         return self.get_auth()['access_token']
     else:
         # It is expected that with dynamic authentication we get a token that
         # is valid at least for a few future seconds, because we don't get
         # any password or permanent permission for it from the user.
         raise DatabaseError(
             "Dynamically authenticated connection can never reauthenticate."
         )
示例#6
0
def prep_for_deserialize(model, record, using, init_list=None):
    """
    Convert a record from SFDC (decoded JSON) to dict(model string, pk, fields)
    If fixes fields of some types. If names of required fields `init_list `are
    specified, then only these fields are processed.
    """
    from salesforce.backend import base
    # TODO the parameter 'using' is not currently important.
    attribs = record.pop('attributes')

    mod = model.__module__.split('.')
    if (mod[-1] == 'models'):
        app_label = mod[-2]
    elif (hasattr(model._meta, 'app_label')):
        app_label = getattr(model._meta, 'app_label')
    else:
        raise ImproperlyConfigured(
            "Can't discover the app_label for %s, you must specify it via model meta options."
        )

    if len(record.keys()) == 1 and model._meta.db_table in record:
        # this is for objects with ManyToManyField and OneToOneField
        while len(record) == 1:
            record = list(record.values())[0]
            if record is None:
                return None

    fields = prep_for_deserialize_inner(model, record, init_list=init_list)

    if init_list and set(init_list).difference(fields).difference([SF_PK]):
        raise DatabaseError("Not found some expected fields")

    return dict(
        model='.'.join([app_label, model.__name__]),
        pk=record.pop('Id'),
        fields=fields,
    )
示例#7
0
    def as_sql(self, with_limits=True, with_col_aliases=False, subquery=False):
        """
        Creates the SQL for this query. Returns the SQL string and list of
        parameters.

        If 'with_limits' is False, any limit/offset information is not included
        in the query.
        """
        # After executing the query, we must get rid of any joins the query
        # setup created. So, take note of alias counts before the query ran.
        # However we do not want to get rid of stuff done in pre_sql_setup(),
        # as the pre_sql_setup will modify query state in a way that forbids
        # another run of it.
        if DJANGO_19_PLUS:
            if with_limits and self.query.low_mark == self.query.high_mark:
                return '', ()
        self.subquery = subquery
        refcounts_before = self.query.alias_refcount.copy()
        soql_trans = self.query_topology()
        try:
            extra_select, order_by, group_by = self.pre_sql_setup()
            if with_limits and self.query.low_mark == self.query.high_mark:
                return '', ()
            distinct_fields = self.get_distinct()

            # This must come after 'select', 'ordering', and 'distinct' -- see
            # docstring of get_from_clause() for details.
            from_, f_params = self.get_from_clause()

            if DJANGO_19_PLUS:
                where, w_params = self.compile(
                    self.where) if self.where is not None else ("", [])
                having, h_params = self.compile(
                    self.having) if self.having is not None else ("", [])
            else:
                where, w_params = self.compile(self.query.where)
                having, h_params = self.compile(self.query.having)
            params = []
            result = ['SELECT']

            if self.query.distinct:
                result.append(
                    self.connection.ops.distinct_sql(distinct_fields))

            out_cols = []
            col_idx = 1
            for _, (s_sql, s_params), alias in self.select + extra_select:
                if alias:
                    # fixed by removing 'AS'
                    s_sql = '%s %s' % (s_sql,
                                       self.connection.ops.quote_name(alias))
                elif with_col_aliases and not isinstance(
                        with_col_aliases,
                        salesforce.backend.base.DatabaseWrapper):
                    s_sql = '%s AS %s' % (s_sql, 'Col%d' % col_idx)
                    col_idx += 1
                if soql_trans and re.match(r'^\w+\.\w+$', s_sql):
                    tab_name, col_name = s_sql.split('.')
                    s_sql = '%s.%s' % (soql_trans[tab_name], col_name)
                params.extend(s_params)
                out_cols.append(s_sql)

            result.append(', '.join(out_cols))

            result.append('FROM')
            result.extend(from_)
            params.extend(f_params)

            if where:
                result.append('WHERE %s' % where)
                params.extend(w_params)

            grouping = []
            for g_sql, g_params in group_by:
                grouping.append(g_sql)
                params.extend(g_params)
            if grouping:
                if distinct_fields:
                    raise NotImplementedError(
                        "annotate() + distinct(fields) is not implemented.")
                if not order_by:
                    order_by = self.connection.ops.force_no_ordering()
                result.append('GROUP BY %s' % ', '.join(grouping))

            if having:
                result.append('HAVING %s' % having)
                params.extend(h_params)

            if order_by:
                ordering = []
                for _, (o_sql, o_params, _) in order_by:
                    ordering.append(o_sql)
                    params.extend(o_params)
                result.append('ORDER BY %s' % ', '.join(ordering))

            if with_limits:
                if self.query.high_mark is not None:
                    result.append('LIMIT %d' %
                                  (self.query.high_mark - self.query.low_mark))
                if self.query.low_mark:
                    if self.query.high_mark is None:
                        val = self.connection.ops.no_limit_value()
                        if val:
                            result.append('LIMIT %d' % val)
                    result.append('OFFSET %d' % self.query.low_mark)

            if self.query.select_for_update and self.connection.features.has_select_for_update:
                if self.connection.get_autocommit():
                    raise TransactionManagementError(
                        "select_for_update cannot be used outside of a transaction."
                    )

                # If we've been asked for a NOWAIT query but the backend does
                # not support it, raise a DatabaseError otherwise we could get
                # an unexpected deadlock.
                nowait = self.query.select_for_update_nowait
                if nowait and not self.connection.features.has_select_for_update_nowait:
                    raise DatabaseError(
                        'NOWAIT is not supported on this database backend.')
                result.append(
                    self.connection.ops.for_update_sql(nowait=nowait))

            return ' '.join(result), tuple(params)
        finally:
            # Finally do cleanup - get rid of the joins we created above.
            self.query.reset_refcounts(refcounts_before)