docs: def fetch_query_from_pgdb(self, qname, query, con, cxn, limit=None, force=False):
          """
          Supply either an already established connection, or connection parameters.
          The supplied connection will override any separate cxn parameter
          :param qname:  The name of the query to save the output to
          :param query:  The SQL query itself
          :param con:  The already-established connection
          :param cxn: The postgres connection information
          :param limit: If you only want a subset of rows from the query
          :return:
          """
          if con is None and cxn is None:
              LOG.error("ERROR: you need to supply connection information")
              return
          if con is None and cxn is not None:
              con = psycopg2.connect(
                  host=cxn['host'], database=cxn['database'], port=cxn['port'],
                  user=cxn['user'], password=cxn['password'])
  
          outfile = '/'.join((self.rawdir, qname))
          cur = con.cursor()
          # wrap the query to get the count
          countquery = ' '.join(("SELECT COUNT(*) FROM (", query, ") x"))
          if limit is not None:
              countquery = ' '.join((countquery, "LIMIT", str(limit)))
  
          # check local copy.
          # assume that if the # rows are the same, that the table is the same
          # TEC - opinion:
          #    the only thing to assume is that if the counts are different
          #    is the data could not be the same.
          #
          #    i.e: for MGI, the dbinfo table has a single row that changes
          #    to check if they are the same sort & compare digests. (
          filerowcount = -1
          tablerowcount = -1
          if not force:
              if os.path.exists(outfile):
                  # get rows in the file
                  filerowcount = self.file_len(outfile)
                  LOG.info("INFO: rows in local file: %s", filerowcount)
  
              # get rows in the table
              # tablerowcount=cur.rowcount
              cur.execute(countquery)
              tablerowcount = cur.fetchone()[0]
  
          # rowcount-1 because there's a header
          if force or filerowcount < 0 or (filerowcount-1) != tablerowcount:
              if force:
                  LOG.info("Forcing download of %s", qname)
              else:
                  LOG.info(
                      "%s local (%s) different from remote (%s); fetching.",
                      qname, filerowcount, tablerowcount)
              # download the file
              LOG.debug("COMMAND:%s", query)
              outputquery = """
      COPY ({0}) TO STDOUT WITH DELIMITER AS '\t' CSV HEADER""".format(query)
              with open(outfile, 'w') as f:
                  cur.copy_expert(outputquery, f)
              # Regenerate row count to check integrity
              filerowcount = self.file_len(outfile)
              if (filerowcount-1) < tablerowcount:
                  raise Exception(
                      "Download from %s failed, %s != %s", cxn['host'] + ':' +
                      cxn['database'], (filerowcount-1), tablerowcount)
              elif (filerowcount-1) > tablerowcount:
                  LOG.warning(
                      "Fetched from %s more rows in file (%s) than reported in count(%s)",
                      cxn['host'] + ':'+cxn['database'], (filerowcount-1), tablerowcount)
          else:
              LOG.info("local data same as remote; reusing.")
  
          return