code: def columns(self, recurse=True, flags=0):
          
          key = (recurse, flags)
          try:
              return self.__cache[key]
          except KeyError:
  
              output = odict()
  
              if recurse:
                  inherits = self.inherits()
                  if inherits:
                      schema = orb.system.schema(inherits)
                      if not schema:
                          raise orb.errors.ModelNotFound(schema=inherits)
                      else:
                          # lookup ancestor columns (don't care about virtual columns)
                          iflags = (flags & ~orb.Column.Flags.Virtual) if flags else ~orb.Column.Flags.Virtual
                          ancest_columns = schema.columns(recurse=recurse, flags=iflags)
                          dups = set(ancest_columns.keys()).intersection(output.keys())
                          if dups:
                              raise orb.errors.DuplicateColumnFound(schema=self, column=','.join(dups))
                          else:
                              output.update(ancest_columns)
  
              output.update(odict(
                  (col.name(), col) for col
                  in sorted(self.__columns.values(), key=lambda x: x.order())
                  if (not flags or col.testFlag(flags))
              ))
  
              self.__cache[key] = output
              return output
docs: Returns the list of column instances that are defined
          for this table schema instance.
          
          :param      recurse | <bool>
                      flags   | <orb.Column.Flags>
                      kind    | <orb.Column.Kind>
          
          :return     {<str> column name: <orb.Column>, ..}