Exemple #1
0
    def first(self, **context):
        if self.isNull():
            return None

        context = self.context(**context)

        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['first'][context]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    return self.__cache['first'][context]
            except IndexError:
                return None
            except KeyError:
                try:
                    with ReadLocker(self.__cacheLock):
                        raw = self.__preload['first'][context]
                except KeyError:
                    context.limit = 1
                    context.order = [(self.__model.schema().idColumn().name(),
                                      'desc')]
                    records = self.records(context=context)
                    record = records[0] if records else None
                else:
                    record = self._process([raw], context)[0]

                with WriteLocker(self.__cacheLock):
                    self.__cache['first'][context] = record
                return record
Exemple #2
0
    def count(self, **context):
        if self.isNull():
            return 0

        context = self.context(**context)
        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['count'][context]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    return len(self.__cache['records'][context])
            except KeyError:
                optimized_context = context.copy()
                optimized_context.columns = [self.__model.schema().idColumn()]
                optimized_context.expand = None
                optimized_context.order = None

                try:
                    with ReadLocker(self.__cacheLock):
                        count = self.__preload['count'][context]
                except KeyError:
                    try:
                        with ReadLocker(self.__cacheLock):
                            raw = self.__preload['records'][context]
                            count = len(raw)
                    except KeyError:
                        conn = optimized_context.db.connection()
                        count = conn.count(self.__model, optimized_context)

                with WriteLocker(self.__cacheLock):
                    self.__cache['count'][context] = count
                return count
Exemple #3
0
    def changes(self, columns=None, recurse=True, flags=0, inflated=False):
        """
        Returns a dictionary of changes that have been made
        to the data from this record.

        :return     { <orb.Column>: ( <variant> old, <variant> new), .. }
        """
        output = {}
        is_record = self.isRecord()
        schema = self.schema()
        columns = [schema.column(c) for c in columns] if columns else \
                   schema.columns(recurse=recurse, flags=flags).values()

        context = self.context(inflated=inflated)
        with ReadLocker(self.__dataLock):
            for col in columns:
                old, curr = self.__values.get(col.name(), (None, None))
                if col.testFlag(col.Flags.ReadOnly):
                    continue
                elif not is_record:
                    old = None

                check_old = col.restore(old, context)
                check_curr = col.restore(curr, context)
                try:
                    different = check_old != check_curr
                except StandardError:
                    different = True

                if different:
                    output[col] = (check_old, check_curr)

        return output
Exemple #4
0
    def value(self, key, default=None):
        """
        Returns the value for the cached key for this instance.

        :return     <variant>
        """
        with ReadLocker(self._cacheLock):
            return self._cache.get(key)
Exemple #5
0
 def index(self, record, **context):
     context = self.context(**context)
     if not record:
         return -1
     else:
         try:
             with ReadLocker(self.__cacheLock):
                 return self.__cache['records'][context].index(record)
         except KeyError:
             return self.ids().index(record.id())
Exemple #6
0
 def current(threadId=None):
     """
     Returns the current transaction for the system.
     
     :return     <Transaction> || None
     """
     threadId = threadId or threading.current_thread().ident
     with ReadLocker(Transaction._stackLock):
         stack = Transaction._stack.get(threadId)
         return stack[-1] if stack else None
Exemple #7
0
    def last(self, **context):
        if self.isNull():
            return None

        context = self.context(**context)
        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['last'][context]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    raw = self.__preload['last'][context]
            except KeyError:
                record = self.reversed().first(context=context)
            else:
                record = self._process([raw], context)[0]

            with WriteLocker(self.__cacheLock):
                self.__cache['last'][context] = record
            return record
Exemple #8
0
    def ids(self, **context):
        if self.isNull():
            return []

        context = self.context(**context)
        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['ids'][context]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    ids = self.__preload['ids'][context]
            except KeyError:
                ids = self.records(columns=[self.__model.schema().idColumn()],
                                   returning='values',
                                   context=context)

            with WriteLocker(self.__cacheLock):
                self.__cache['ids'][context] = ids

            return ids
Exemple #9
0
    def copy(self, **context):
        context = self.context(**context)

        with ReadLocker(self.__cacheLock):
            records = self.__cache['records'].get(context)

        other = orb.Collection(records=records,
                               preload=self.__preload,
                               model=self.__model,
                               record=self.__record,
                               collector=self.__collector,
                               context=context)
        return other
Exemple #10
0
    def records(self, **context):
        if self.isNull():
            return []

        context = self.context(**context)

        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['records'][context]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    raw = self.__preload['records'][context]
            except KeyError:
                conn = context.db.connection()
                raw = conn.select(self.__model, context)

            records = self._process(raw, context)

            with WriteLocker(self.__cacheLock):
                self.__cache['records'][context] = records
            return records
Exemple #11
0
    def defaultContexts(cls):
        defaults = getattr(cls, '_{0}__defaults'.format(cls.__name__), None)
        if defaults is None:
            defaults = defaultdict(list)
            lock = ReadWriteLock()
            setattr(cls, '_{0}__defaults'.format(cls.__name__), defaults)
            setattr(cls, '_{0}__defaultsLock'.format(cls.__name__), lock)
        else:
            lock = getattr(cls, '_{0}__defaultsLock'.format(cls.__name__))

        tid = threading.currentThread().ident
        with ReadLocker(lock):
            return defaults.get(tid) or []
Exemple #12
0
    def isCached(self, key):
        """
        Returns whether or not the inputted key is cached.

        :param      key | <hashable>

        :return     <bool>
        """
        if not self.isEnabled():
            return False

        self._cleanup()

        with ReadLocker(self._cacheLock):
            return key in self._cache
Exemple #13
0
    def refine(self, createNew=True, **context):
        if not createNew:
            self.__context.update(context)
            return self
        else:
            context = self.context(**context)
            with ReadLocker(self.__cacheLock):
                records = self.__cache['records'].get(context)

            other = orb.Collection(records=records,
                                   model=self.__model,
                                   record=self.__record,
                                   collector=self.__collector,
                                   context=context)
            return other
Exemple #14
0
    def isRecord(self, db=None):
        """
        Returns whether or not this database table record exists
        in the database.

        :return     <bool>
        """
        if db in (None, self.context().db):
            col = self.schema().column(self.schema().idColumn())
            with ReadLocker(self.__dataLock):
                if col not in self.__loaded or self.__values[
                        col.name()][0] is None:
                    return False
                return True
        else:
            return None
Exemple #15
0
    def select(self, table_or_join, lookup, options):
        if orb.Table.typecheck(table_or_join) or orb.View.typecheck(
                table_or_join):
            # ensure the primary record information is provided for orb.logger.setLevel(orb.logging.DEBUG)ions
            if lookup.columns and options.inflated:
                lookup.columns += [
                    col.name()
                    for col in table_or_join.schema().primaryColumns()
                ]

            SELECT = self.sql().byName('SELECT')

            schema = table_or_join.schema()
            data = {}
            sql = SELECT(table_or_join,
                         lookup=lookup,
                         options=options,
                         IO=data)

            # if we don't have any command to run, just return a blank list
            if not sql:
                return []
            elif options.dryRun:
                print sql % data
                return []
            else:
                with ReadLocker(self.__concurrencyLocks[schema.name()]):
                    records = self.execute(sql, data)[0]

                store = self.sql().datastore()
                for record in records:
                    for name, value in record.items():
                        column = schema.column(name)
                        record[name] = store.restore(column, value)

                return records
        else:
            raise orb.errors.DatabaseError('JOIN NOT DEFINED')
Exemple #16
0
    def get(self, column, useMethod=True, **context):
        """
        Returns the value for the column for this record.

        :param      column      | <orb.Column> || <str>
                    default     | <variant>
                    inflated    | <bool>

        :return     <variant>
        """
        if isinstance(column, (str, unicode)) and '.' in column:
            parts = column.split('.')
            sub_context = context.copy()
            sub_context['inflated'] = True
            value = self
            for part in parts[:-1]:
                if not value:
                    return None
                value = value.get(part, useMethod=useMethod, **sub_context)

            if value:
                return value.get(parts[-1], useMethod=useMethod, **context)
            else:
                return None
        else:
            my_context = self.context()

            for k, v in my_context.raw_values.items():
                if k not in orb.Context.QueryFields:
                    context.setdefault(k, v)

            sub_context = orb.Context(**context)

            # normalize the given column
            col = self.schema().column(column, raise_=False)
            if not col:
                collector = self.schema().collector(column)
                if collector:
                    try:
                        return self.__cache[collector][sub_context]
                    except KeyError:
                        records = collector(self,
                                            useMethod=useMethod,
                                            context=sub_context)
                        self.__cache[collector][sub_context] = records
                        return records
                else:
                    raise errors.ColumnNotFound(self.schema().name(), column)

            # lookup the shortuct value vs. the local one
            elif col.shortcut():
                return self.get(col.shortcut(), **context)

            # don't inflate if the requested value is a field
            if column == col.field():
                sub_context.inflated = False

            # call the getter method fot this record if one exists
            if useMethod:
                method = col.gettermethod()
                if method is not None:
                    return method(self, context=sub_context)

            # grab the current value
            with ReadLocker(self.__dataLock):
                old_value, value = self.__values.get(col.name(), (None, None))

            # return a reference when desired
            out_value = col.restore(value, sub_context)
            if isinstance(out_value,
                          orb.Model) and not isinstance(value, orb.Model):
                with WriteLocker(self.__dataLock):
                    self.__values[col.name()] = (old_value, out_value)
            return out_value
Exemple #17
0
 def isLoaded(self, **context):
     context = self.context(**context)
     with ReadLocker(self.__cacheLock):
         return context in self.__cache['records']
Exemple #18
0
 def isNull(self):
     with ReadLocker(self.__cacheLock):
         return self.__cache['records'].get(
             self.__context) is None and self.__model is None
Exemple #19
0
    def values(self, *columns, **context):
        if self.isNull():
            return []

        orig_context = context
        context = self.context(**orig_context)

        try:
            with ReadLocker(self.__cacheLock):
                return self.__cache['values'][(context, columns)]
        except KeyError:
            try:
                with ReadLocker(self.__cacheLock):
                    records = self.__cache['records'][context]
            except KeyError:
                try:
                    with ReadLocker(self.__cacheLock):
                        raw = self.__preload['records'][context]
                except KeyError:
                    context.columns = columns
                    conn = context.db.connection()
                    raw = conn.select(self.__model, context)

                schema = self.__model.schema()
                values = []
                fields = [schema.column(col) for col in columns]
                for record in raw:
                    if not context.inflated:
                        record_values = [
                            record[field.field()] for field in fields
                        ]
                    else:
                        record_values = []
                        for i, field in enumerate(fields):
                            col = columns[i]
                            raw_values = orig_context.copy()
                            raw_values['distinct'] = None
                            if isinstance(
                                    field, orb.ReferenceColumn
                            ) and raw_values.get('inflated') is None:
                                raw_values['inflated'] = col != field.field()

                            val = field.restore(
                                record[field.field()],
                                context=orb.Context(**raw_values))
                            record_values.append(val)

                    if len(fields) == 1:
                        values.append(record_values[0])
                    else:
                        values.append(record_values)

                with WriteLocker(self.__cacheLock):
                    self.__cache['values'][(context, columns)] = values
                return values

            # use preloaded cache for values when possible
            else:
                if len(columns) == 1:
                    return [
                        record.get(columns[0]) if record else None
                        for record in records
                    ]
                else:
                    return [(record.get(c) for c in columns)
                            for record in records]