示例#1
0
 def unlock(self):
     """
         Unlock the record
     """
     # Locking is done via an M level routine on the record global
     g_path = self._dd.m_closed_form(self._rowid)
     M.mexec(str("LOCK -%s" % g_path))   # TODO: mexec to take unicode
示例#2
0
文件: dbsdd.py 项目: rmurray1/vavista
 def fileid(self):
     """
         Look up the ^DIC array and find the file number for the specified file, 
         e.g. FILE = 1 - result is a string.
     """
     if self._fileid is None:
         rv = M.mexec("""set s1=$order(^DIC("B",s0,0))""", str(self.filename[:30]), M.INOUT(""))[0]
         if rv != "":
             self._fileid = rv
     return self._fileid
示例#3
0
文件: dbsdd.py 项目: whitten/vavista
 def fileid(self):
     """
         Look up the ^DIC array and find the file number for the specified file, 
         e.g. FILE = 1 - result is a string.
     """
     if self._fileid is None:
         rv = M.mexec('''set s1=$order(^DIC("B",s0,0))''',
                      str(self.filename[:30]), M.INOUT(""))[0]
         if rv != '':
             self._fileid = rv
     return self._fileid
示例#4
0
    def lock(self, timeout=5):
        """
            Lock a record.
        """
        g_path = self._dd.m_closed_form(self._rowid)

        # Set the timeout
        M.Globals["DILOCKTM"].value = timeout

        # use DILF^LOCK function to perform the lock
        M.proc("LOCK^DILF", g_path)

        # result is returned in $T
        rv, = M.mexec("set l0=$T", M.INOUT(0))
        if rv != 1:
            raise FilemanLockFailed(filename=self._dd.filename, row=self._rowid, timeout=timeout)
示例#5
0
    def list_files(self):
        """
            Oddly, I cannot see how to list the files using the DBS API.
            This is required for debugging etc.
        """
        if self.remote:
            return self.remote.list_files()

        M.mset('DUZ',self.DUZ)
        M.mset('U', "^")
        if self.isProgrammer:
            M.mset('DUZ(0)', "@")
        rv = []
        s0 = "0"
        while s0 != "":
            s0, name = M.mexec(
                '''set s0=$order(^DIC(s0)) Q:s0'=+s0  I $D(^DIC(s0,0))&$D(^DIC(s0,0,"GL"))&$$VFILE^DILFD(s0) S s1=$P(^DIC(s0,0),U,1)''',
                M.INOUT(s0), M.INOUT(""))
            if name:
                rv.append((name, s0))
        return rv
示例#6
0
    def next(self):
        lastkey = self.lastkey
        lastrowid = self.lastrowid
        if self.ascending:
            asc = 1
        else:
            asc = -1

        # TODO: Fileman seems to structure indices with keys in the global path
        #       or in the value - need to investigate further

        # There is a mad collation approach in M, where numbers sort before non-numbers.
        # this really messes up the keys.
        # How should I search? 

        # There is an inefficiency here it takes three searches to find the next record.
        while 1:
            if lastrowid is None:
                # locate the next matching index value
                lastkey, = M.mexec("""set s0=$order(%ss0),%s)""" % (self.gl, asc), M.INOUT(str(lastkey)))
                if lastkey == "":
                    break

                if self.ascending:
                    if self.from_value is not None:
                        if self.from_rule == ">" and lastkey <= self.from_value:
                            continue
                        if self.from_rule == ">=" and lastkey < self.from_value:
                            assert 0
                    if self.to_value is not None:
                        if self.to_rule == "<=" and lastkey > self.to_value:
                            break
                        if self.to_rule == "=" and lastkey != self.to_value:
                            break
                        if self.to_rule == "<" and lastkey >= self.to_value:
                            break
                    self.lastkey = lastkey
                    lastrowid = "0"

                else: # descending
                    if self.from_value is not None:
                        if self.from_rule == "<" and lastkey >= self.from_value:
                            continue
                        if self.from_rule == "<=" and lastkey > self.from_value:
                            assert 0
                    if self.to_value is not None:
                        if self.to_rule == ">=" and lastkey < self.to_value:
                            break
                        if self.to_rule == "=" and lastkey != self.to_value:
                            break
                        if self.to_rule == ">" and lastkey <= self.to_value:
                            break
                    self.lastkey = lastkey
                    lastrowid = ""

            # Have the key, get the first matching rowid
            lastrowid, = M.mexec("""set s0=$order(%s"%s",s1),%d)""" % (self.gl, self.lastkey, asc),
                    M.INOUT(str(lastkey)), lastrowid)
            if lastrowid == "":
                # No match
                lastrowid = None
                continue

            if self.filters:
                # Are filters to be applied?
                if not self.filters(lastrowid):
                    continue

            if self.skip_rows > 0:
                self.skip_rows -= 1
                continue

            self.lastrowid = lastrowid
            if self.raw:
                return self.lastkey, self.lastrowid
            return self.getter(self.lastrowid)

        raise StopIteration
示例#7
0
    def next(self):

        # Have we exceeded limit
        if self.limit and self.results_returned >= self.limit:
            raise StopIteration

        lastrowid = self.lastrowid    # This value should be a string throughout. 
        if self.ascending:
            asc = 1
        else:
            asc = -1

        while not self.results_complete:
            # If this is the first pass, we may have the id of a record, which needs to 
            # be verified
            found = False
            if self.first_pass:
                self.first_pass = False
                if lastrowid is None and asc == -1:
                    lastrowid, = M.mexec("""set s0=$order(%ss0),-1)""" % self.gl, M.INOUT('%'))
                    if valid_rowid(lastrowid):
                        found = True
                elif lastrowid and float(lastrowid) > 0:
                    row_exists, = M.mexec("""set s0=$data(%ss0))""" % (self.gl), M.INOUT(lastrowid))
                    if valid_rowid(row_exists):
                        found = True

            if not found:
                lastrowid, = M.mexec("""set s0=$order(%ss0),%d)""" % (self.gl, asc), M.INOUT(lastrowid))
                if not valid_rowid(lastrowid):
                    break

            # Check boundary values
            f_lastrowid = float(lastrowid)
            if self.ascending:
                if self.from_rowid is not None:
                    if f_lastrowid == self.from_rowid and self.from_rule == ">":
                        continue
                if self.to_rowid is not None:
                    if f_lastrowid >= self.to_rowid and self.to_rule == "<":
                        break
                    if f_lastrowid > self.to_rowid and self.to_rule == "<=":
                        break
            else: # descending:
                if f_lastrowid == 0:
                    break # header record 
                if self.from_rowid is not None:
                    if f_lastrowid == self.from_rowid and self.from_rule == "<":
                        continue
                if self.to_rowid is not None:
                    if f_lastrowid <= self.to_rowid and self.to_rule == ">":
                        break
                    if f_lastrowid < self.to_rowid and self.to_rule == ">=":
                        break

            if self.filters:
                # Are filters to be applied?
                if not self.filters(lastrowid):
                    continue

            if self.skip_rows > 0:
                self.skip_rows -= 1
                continue

            self.lastrowid = lastrowid

            self.results_returned += 1

            if self.raw:
                return self.lastrowid
            return self.getter(self.lastrowid)

        self.results_complete = True
        raise StopIteration
示例#8
0
    def next(self):
        lastkey = self.lastkey
        lastrowid = self.lastrowid
        if self.ascending:
            asc = 1
        else:
            asc = -1

        # TODO: Fileman seems to structure indices with keys in the global path
        #       or in the value - need to investigate further

        # There is a mad collation approach in M, where numbers sort before non-numbers.
        # this really messes up the keys.
        # How should I search?

        # There is an inefficiency here it takes three searches to find the next record.
        while 1:
            if lastrowid is None:
                # locate the next matching index value
                lastkey, = M.mexec(
                    """set s0=$order(%ss0),%s)""" % (self.gl, asc),
                    M.INOUT(str(lastkey)))
                if lastkey == "":
                    break

                if self.ascending:
                    if self.from_value is not None:
                        if self.from_rule == ">" and lastkey <= self.from_value:
                            continue
                        if self.from_rule == ">=" and lastkey < self.from_value:
                            assert 0
                    if self.to_value is not None:
                        if self.to_rule == "<=" and lastkey > self.to_value:
                            break
                        if self.to_rule == "=" and lastkey != self.to_value:
                            break
                        if self.to_rule == "<" and lastkey >= self.to_value:
                            break
                    self.lastkey = lastkey
                    lastrowid = "0"

                else:  # descending
                    if self.from_value is not None:
                        if self.from_rule == "<" and lastkey >= self.from_value:
                            continue
                        if self.from_rule == "<=" and lastkey > self.from_value:
                            assert 0
                    if self.to_value is not None:
                        if self.to_rule == ">=" and lastkey < self.to_value:
                            break
                        if self.to_rule == "=" and lastkey != self.to_value:
                            break
                        if self.to_rule == ">" and lastkey <= self.to_value:
                            break
                    self.lastkey = lastkey
                    lastrowid = ""

            # Have the key, get the first matching rowid
            lastrowid, = M.mexec(
                """set s0=$order(%s"%s",s1),%d)""" %
                (self.gl, self.lastkey, asc), M.INOUT(str(lastkey)), lastrowid)
            if lastrowid == "":
                # No match
                lastrowid = None
                continue

            if self.filters:
                # Are filters to be applied?
                if not self.filters(lastrowid):
                    continue

            if self.skip_rows > 0:
                self.skip_rows -= 1
                continue

            self.lastrowid = lastrowid
            if self.raw:
                return self.lastkey, self.lastrowid
            return self.getter(self.lastrowid)

        raise StopIteration
示例#9
0
    def next(self):

        # Have we exceeded limit
        if self.limit and self.results_returned >= self.limit:
            raise StopIteration

        lastrowid = self.lastrowid  # This value should be a string throughout.
        if self.ascending:
            asc = 1
        else:
            asc = -1

        while not self.results_complete:
            # If this is the first pass, we may have the id of a record, which needs to
            # be verified
            found = False
            if self.first_pass:
                self.first_pass = False
                if lastrowid is None and asc == -1:
                    lastrowid, = M.mexec(
                        """set s0=$order(%ss0),-1)""" % self.gl, M.INOUT('%'))
                    if valid_rowid(lastrowid):
                        found = True
                elif lastrowid and float(lastrowid) > 0:
                    row_exists, = M.mexec(
                        """set s0=$data(%ss0))""" % (self.gl),
                        M.INOUT(lastrowid))
                    if valid_rowid(row_exists):
                        found = True

            if not found:
                lastrowid, = M.mexec(
                    """set s0=$order(%ss0),%d)""" % (self.gl, asc),
                    M.INOUT(lastrowid))
                if not valid_rowid(lastrowid):
                    break

            # Check boundary values
            f_lastrowid = float(lastrowid)
            if self.ascending:
                if self.from_rowid is not None:
                    if f_lastrowid == self.from_rowid and self.from_rule == ">":
                        continue
                if self.to_rowid is not None:
                    if f_lastrowid >= self.to_rowid and self.to_rule == "<":
                        break
                    if f_lastrowid > self.to_rowid and self.to_rule == "<=":
                        break
            else:  # descending:
                if f_lastrowid == 0:
                    break  # header record
                if self.from_rowid is not None:
                    if f_lastrowid == self.from_rowid and self.from_rule == "<":
                        continue
                if self.to_rowid is not None:
                    if f_lastrowid <= self.to_rowid and self.to_rule == ">":
                        break
                    if f_lastrowid < self.to_rowid and self.to_rule == ">=":
                        break

            if self.filters:
                # Are filters to be applied?
                if not self.filters(lastrowid):
                    continue

            if self.skip_rows > 0:
                self.skip_rows -= 1
                continue

            self.lastrowid = lastrowid

            self.results_returned += 1

            if self.raw:
                return self.lastrowid
            return self.getter(self.lastrowid)

        self.results_complete = True
        raise StopIteration
示例#10
0
文件: dbsdd.py 项目: whitten/vavista
    def indices(self):
        """
            Return a list of the indices

            To be valid, the index must be both in the IX

            ^DD(200,0,"IX","AASWB",200,654)=""

        """
        if self._indices is None:
            i = []

            # TODO: this is not right for multi-column keys
            # TODO: new style indexes

            global_name = '^DD(%s,0,"IX","0")' % self.fileid
            prefix = '^DD(%s,0,"IX",' % self.fileid
            while 1:
                global_name = M.mexec('set s0=$query(%s)' % global_name,
                                      M.INOUT(""))[0]
                if not global_name or not global_name.startswith(prefix):
                    break
                suffix = global_name[len(prefix):-1]
                parts = suffix.split(",")
                idx_name = parts[0][1:-1]
                idx_table = parts[1]
                idx_columns = parts[2:]
                index = Index(idx_name, idx_table, idx_columns)
                i.append(index)

            # A second list, gives indices for a field
            columns = {}
            for idx in i:
                for c in idx.columns:
                    columns[c] = 1

            # Now trawl the listed columns in the data dictionary, and load their
            # cross references.
            cr_names = {}
            for c in columns.keys():
                idx_root = M.Globals["^DD"][self.fileid][c][1]
                if not idx_root[0].exists():
                    continue
                for cr_id, val in idx_root.keys_with_decendants():
                    if float(cr_id) > 0:
                        cr_header = idx_root[cr_id][0].value
                        parts = cr_header.split("^")
                        if len(parts) == 2 and parts[
                                1]:  # if more than 2 parts, assume MUMPs trigger
                            f = cr_names.get(parts[1], list())
                            f.append(c)
                            cr_names[parts[1]] = f

            # Now, just delete items from the index list if they are not in cr_names
            self._indices = []
            for index in i:
                cr = cr_names.get(index.name)
                if cr:
                    # verify columns - lots of errors in real systems
                    if len(cr) == len(index.columns):
                        invalid = False
                        for c in cr:
                            if c not in index.columns:
                                invalid = True
                                continue
                        if not invalid:
                            self._indices.append(index)

        return self._indices
示例#11
0
文件: dbsdd.py 项目: rmurray1/vavista
    def indices(self):
        """
            Return a list of the indices

            To be valid, the index must be both in the IX

            ^DD(200,0,"IX","AASWB",200,654)=""

        """
        if self._indices is None:
            i = []

            # TODO: this is not right for multi-column keys
            # TODO: new style indexes

            global_name = '^DD(%s,0,"IX","0")' % self.fileid
            prefix = '^DD(%s,0,"IX",' % self.fileid
            while 1:
                global_name = M.mexec("set s0=$query(%s)" % global_name, M.INOUT(""))[0]
                if not global_name or not global_name.startswith(prefix):
                    break
                suffix = global_name[len(prefix) : -1]
                parts = suffix.split(",")
                idx_name = parts[0][1:-1]
                idx_table = parts[1]
                idx_columns = parts[2:]
                index = Index(idx_name, idx_table, idx_columns)
                i.append(index)

            # A second list, gives indices for a field
            columns = {}
            for idx in i:
                for c in idx.columns:
                    columns[c] = 1

            # Now trawl the listed columns in the data dictionary, and load their
            # cross references.
            cr_names = {}
            for c in columns.keys():
                idx_root = M.Globals["^DD"][self.fileid][c][1]
                if not idx_root[0].exists():
                    continue
                for cr_id, val in idx_root.keys_with_decendants():
                    if float(cr_id) > 0:
                        cr_header = idx_root[cr_id][0].value
                        parts = cr_header.split("^")
                        if len(parts) == 2 and parts[1]:  # if more than 2 parts, assume MUMPs trigger
                            f = cr_names.get(parts[1], list())
                            f.append(c)
                            cr_names[parts[1]] = f

            # Now, just delete items from the index list if they are not in cr_names
            self._indices = []
            for index in i:
                cr = cr_names.get(index.name)
                if cr:
                    # verify columns - lots of errors in real systems
                    if len(cr) == len(index.columns):
                        invalid = False
                        for c in cr:
                            if c not in index.columns:
                                invalid = True
                                continue
                        if not invalid:
                            self._indices.append(index)

        return self._indices
示例#12
0
def index_order_traversal(gl_prefix,
                          index,
                          ranges=None,
                          ascending=True,
                          sf_path=[],
                          explain=False):
    """
        A generator which will traverse an index.
        The iterator should yield rowids.

            Indices are stored:
                GLOBAL,INDEXID,VALUE,ROWID=""
            ^DIZ(999900,"B","hello there from unit test2",183)=""
            ^DIZ(999900,"B","hello there from unit test2",184)=""
            ^DIZ(999900,"B","hello there from unit test2",185)=""
            ^DIZ(999900,"B","record 1",1)=""

    """
    gl = gl_prefix + '"%s",' % index

    if ranges:
        r = ranges[0]
        from_value = r['from_value']
        to_value = r['to_value']
        from_rule = r['from_rule']
        to_rule = r['to_rule']
    else:
        from_value, to_value, from_rule, to_rule = None, None, None, None

    if explain:
        yield "index_order_traversal, ascending=%s, gl=%s, index=%s, X %s '%s' AND X %s '%s'" % (
            ascending, gl, index, from_rule, from_value, to_rule, to_value)
        return

    if from_value != None and to_value != None:
        if ascending:
            assert (from_value <= to_value)
        else:
            assert (to_value <= from_value)

    if from_value is None:
        if ascending:
            lastkey = " "
        else:
            lastkey = "ZZZZZZZZZZZZZZ"
        lastrowid = ""
    else:
        lastkey = from_value
        if from_rule == '>':
            lastrowid = None  # looks for the next key after lastkey
        else:
            lastrowid = ''  # looks for the lastkey

    if ascending:
        asc = 1
    else:
        asc = -1

    # TODO: Fileman seems to structure indices with keys in the global path
    #       or in the value - need to investigate further

    # There is a mad collation approach in M, where numbers sort before non-numbers.
    # this really messes up the keys.
    # How should I search?

    # There is an inefficiency here it takes three searches to find the next record.
    while 1:
        if lastrowid is None:
            # locate the next matching index value
            lastkey, = M.mexec("""set s0=$order(%ss0),%s)""" % (gl, asc),
                               M.INOUT(str(lastkey)))
            if lastkey == "":
                break

            if ascending:
                if from_value is not None:
                    if from_rule == ">" and lastkey <= from_value:
                        continue
                    if from_rule == ">=" and lastkey < from_value:
                        assert 0
                if to_value is not None:
                    if to_rule == "<=" and lastkey > to_value:
                        break
                    if to_rule == "=" and lastkey != to_value:
                        break
                    if to_rule == "<" and lastkey >= to_value:
                        break
                lastkey = lastkey
                lastrowid = "0"

            else:  # descending
                if from_value is not None:
                    if from_rule == "<" and lastkey >= from_value:
                        continue
                    if from_rule == "<=" and lastkey > from_value:
                        assert 0
                if to_value is not None:
                    if to_rule == ">=" and lastkey < to_value:
                        break
                    if to_rule == "=" and lastkey != to_value:
                        break
                    if to_rule == ">" and lastkey <= to_value:
                        break
                lastkey = lastkey
                lastrowid = ""

        # Have the key, get the first matching rowid
        lastrowid, = M.mexec(
            """set s0=$order(%s"%s",s1),%d)""" % (gl, lastkey, asc),
            M.INOUT(str(lastkey)), lastrowid)
        if lastrowid == "":
            # No match
            lastrowid = None
            continue

        yield (lastrowid, "%s%s)" % (gl_prefix, lastrowid),
               sf_path + [lastrowid])
示例#13
0
def file_order_traversal(gl,
                         ranges=None,
                         ascending=True,
                         sf_path=[],
                         explain=False):
    """
        Originate records by traversing the file in file order (i.e. no index)
    """
    if ranges:
        r = ranges[0]
        from_rowid = r['from_value']
        to_rowid = r['to_value']
        from_rule = r['from_rule']
        to_rule = r['to_rule']
    else:
        from_rowid, to_rowid, from_rule, to_rule = None, None, None, None

    if explain:
        yield "file_order_traversal, ascending=%s, gl=%s, X %s %s AND X %s %s" % (
            ascending, gl, from_rule, from_rowid, to_rule, to_rowid)
        return

    # the new person file has non-integer user ids
    if from_rowid != None:
        from_rowid = float(from_rowid)
    if to_rowid != None:
        to_rowid = float(to_rowid)

    if from_rowid != None and to_rowid != None:
        if ascending:
            assert (from_rowid <= to_rowid)
        else:
            assert (to_rowid <= from_rowid)

    if from_rowid is None:
        if ascending:
            lastrowid = "0"
        else:
            lastrowid = None
    else:
        # TODO: I have this in code in shared
        lastrowid = ('%f' % from_rowid).rstrip('0').rstrip('.').lstrip('0')
        if from_rowid > 0 and lastrowid[0] == "0":
            lastrowid = lastrowid[1:]
        if lastrowid.endswith(".0"):
            lastrowid = lastrowid[:-2]

    first_pass = True

    if ascending:
        asc = 1
    else:
        asc = -1

    while 1:
        # If this is the first pass, we may have the id of a record, which needs to
        # be verified
        found = False
        if first_pass:
            first_pass = False
            if lastrowid is None and asc == -1:
                lastrowid, = M.mexec("""set s0=$order(%ss0),-1)""" % gl,
                                     M.INOUT('%'))
                if valid_rowid(lastrowid):
                    found = True
            elif lastrowid and float(lastrowid) > 0:
                row_exists, = M.mexec("""set s0=$data(%ss0))""" % (gl),
                                      M.INOUT(lastrowid))
                if valid_rowid(row_exists):
                    found = True

        if not found:
            lastrowid, = M.mexec("""set s0=$order(%ss0),%d)""" % (gl, asc),
                                 M.INOUT(lastrowid))
            if not valid_rowid(lastrowid):
                break

        # Check boundary values
        f_lastrowid = float(lastrowid)
        if ascending:
            if from_rowid is not None:
                if f_lastrowid == from_rowid and from_rule == ">":
                    continue
            if to_rowid is not None:
                if f_lastrowid >= to_rowid and to_rule == "<":
                    break
                if f_lastrowid > to_rowid and to_rule == "<=":
                    break
        else:  # descending:
            if f_lastrowid == 0:
                break  # header record
            if from_rowid is not None:
                if f_lastrowid == from_rowid and from_rule == "<":
                    continue
            if to_rowid is not None:
                if f_lastrowid <= to_rowid and to_rule == ">":
                    break
                if f_lastrowid < to_rowid and to_rule == ">=":
                    break

        # If this is a subfile, I need to return the full path.
        yield (lastrowid, "%s%s)" % (gl, lastrowid), sf_path + [lastrowid])
示例#14
0
def index_order_traversal(gl_prefix, index, ranges=None, ascending=True, sf_path=[], explain=False):
    """
        A generator which will traverse an index.
        The iterator should yield rowids.

            Indices are stored:
                GLOBAL,INDEXID,VALUE,ROWID=""
            ^DIZ(999900,"B","hello there from unit test2",183)=""
            ^DIZ(999900,"B","hello there from unit test2",184)=""
            ^DIZ(999900,"B","hello there from unit test2",185)=""
            ^DIZ(999900,"B","record 1",1)=""

    """
    gl = gl_prefix + '"%s",' % index

    if ranges:
        r = ranges[0]
        from_value = r["from_value"]
        to_value = r["to_value"]
        from_rule = r["from_rule"]
        to_rule = r["to_rule"]
    else:
        from_value, to_value, from_rule, to_rule = None, None, None, None

    if explain:
        yield "index_order_traversal, ascending=%s, gl=%s, index=%s, X %s '%s' AND X %s '%s'" % (
            ascending,
            gl,
            index,
            from_rule,
            from_value,
            to_rule,
            to_value,
        )
        return

    if from_value != None and to_value != None:
        if ascending:
            assert from_value <= to_value
        else:
            assert to_value <= from_value

    if from_value is None:
        if ascending:
            lastkey = " "
        else:
            lastkey = "ZZZZZZZZZZZZZZ"
        lastrowid = ""
    else:
        lastkey = from_value
        if from_rule == ">":
            lastrowid = None  # looks for the next key after lastkey
        else:
            lastrowid = ""  # looks for the lastkey

    if ascending:
        asc = 1
    else:
        asc = -1

    # TODO: Fileman seems to structure indices with keys in the global path
    #       or in the value - need to investigate further

    # There is a mad collation approach in M, where numbers sort before non-numbers.
    # this really messes up the keys.
    # How should I search?

    # There is an inefficiency here it takes three searches to find the next record.
    while 1:
        if lastrowid is None:
            # locate the next matching index value
            lastkey, = M.mexec("""set s0=$order(%ss0),%s)""" % (gl, asc), M.INOUT(str(lastkey)))
            if lastkey == "":
                break

            if ascending:
                if from_value is not None:
                    if from_rule == ">" and lastkey <= from_value:
                        continue
                    if from_rule == ">=" and lastkey < from_value:
                        assert 0
                if to_value is not None:
                    if to_rule == "<=" and lastkey > to_value:
                        break
                    if to_rule == "=" and lastkey != to_value:
                        break
                    if to_rule == "<" and lastkey >= to_value:
                        break
                lastkey = lastkey
                lastrowid = "0"

            else:  # descending
                if from_value is not None:
                    if from_rule == "<" and lastkey >= from_value:
                        continue
                    if from_rule == "<=" and lastkey > from_value:
                        assert 0
                if to_value is not None:
                    if to_rule == ">=" and lastkey < to_value:
                        break
                    if to_rule == "=" and lastkey != to_value:
                        break
                    if to_rule == ">" and lastkey <= to_value:
                        break
                lastkey = lastkey
                lastrowid = ""

        # Have the key, get the first matching rowid
        lastrowid, = M.mexec("""set s0=$order(%s"%s",s1),%d)""" % (gl, lastkey, asc), M.INOUT(str(lastkey)), lastrowid)
        if lastrowid == "":
            # No match
            lastrowid = None
            continue

        yield (lastrowid, "%s%s)" % (gl_prefix, lastrowid), sf_path + [lastrowid])
示例#15
0
def file_order_traversal(gl, ranges=None, ascending=True, sf_path=[], explain=False):
    """
        Originate records by traversing the file in file order (i.e. no index)
    """
    if ranges:
        r = ranges[0]
        from_rowid = r["from_value"]
        to_rowid = r["to_value"]
        from_rule = r["from_rule"]
        to_rule = r["to_rule"]
    else:
        from_rowid, to_rowid, from_rule, to_rule = None, None, None, None

    if explain:
        yield "file_order_traversal, ascending=%s, gl=%s, X %s %s AND X %s %s" % (
            ascending,
            gl,
            from_rule,
            from_rowid,
            to_rule,
            to_rowid,
        )
        return

    # the new person file has non-integer user ids
    if from_rowid != None:
        from_rowid = float(from_rowid)
    if to_rowid != None:
        to_rowid = float(to_rowid)

    if from_rowid != None and to_rowid != None:
        if ascending:
            assert from_rowid <= to_rowid
        else:
            assert to_rowid <= from_rowid

    if from_rowid is None:
        if ascending:
            lastrowid = "0"
        else:
            lastrowid = None
    else:
        # TODO: I have this in code in shared
        lastrowid = ("%f" % from_rowid).rstrip("0").rstrip(".").lstrip("0")
        if from_rowid > 0 and lastrowid[0] == "0":
            lastrowid = lastrowid[1:]
        if lastrowid.endswith(".0"):
            lastrowid = lastrowid[:-2]

    first_pass = True

    if ascending:
        asc = 1
    else:
        asc = -1

    while 1:
        # If this is the first pass, we may have the id of a record, which needs to
        # be verified
        found = False
        if first_pass:
            first_pass = False
            if lastrowid is None and asc == -1:
                lastrowid, = M.mexec("""set s0=$order(%ss0),-1)""" % gl, M.INOUT("%"))
                if valid_rowid(lastrowid):
                    found = True
            elif lastrowid and float(lastrowid) > 0:
                row_exists, = M.mexec("""set s0=$data(%ss0))""" % (gl), M.INOUT(lastrowid))
                if valid_rowid(row_exists):
                    found = True

        if not found:
            lastrowid, = M.mexec("""set s0=$order(%ss0),%d)""" % (gl, asc), M.INOUT(lastrowid))
            if not valid_rowid(lastrowid):
                break

        # Check boundary values
        f_lastrowid = float(lastrowid)
        if ascending:
            if from_rowid is not None:
                if f_lastrowid == from_rowid and from_rule == ">":
                    continue
            if to_rowid is not None:
                if f_lastrowid >= to_rowid and to_rule == "<":
                    break
                if f_lastrowid > to_rowid and to_rule == "<=":
                    break
        else:  # descending:
            if f_lastrowid == 0:
                break  # header record
            if from_rowid is not None:
                if f_lastrowid == from_rowid and from_rule == "<":
                    continue
            if to_rowid is not None:
                if f_lastrowid <= to_rowid and to_rule == ">":
                    break
                if f_lastrowid < to_rowid and to_rule == ">=":
                    break

        # If this is a subfile, I need to return the full path.
        yield (lastrowid, "%s%s)" % (gl, lastrowid), sf_path + [lastrowid])