<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _get_fields(self, table_name, **kwargs):
 """return all the fields for the given schema"""

        ret = {}
        query_str = []
        query_args = ['f', table_name]

        # I had to brush up on my join knowledge while writing this query
        # https://en.wikipedia.org/wiki/Join_(SQL)
        #
        # other helpful links
        # https://wiki.postgresql.org/wiki/Retrieve_primary_key_columns
        # https://www.postgresql.org/docs/9.4/static/catalog-pg-attribute.html
        # https://www.postgresql.org/docs/9.3/static/catalog-pg-type.html
        # 
        # another approach
        # http://dba.stackexchange.com/questions/22362/how-do-i-list-all-columns-for-a-specified-table
        # http://gis.stackexchange.com/questions/94049/how-to-get-the-data-type-of-each-column-from-a-postgis-table
        query_str.append('SELECT')
        query_str.append(',  '.join([
            'a.attnum',
            'a.attname',
            'a.attnotnull',
            't.typname',
            'i.indisprimary',
            #'s.conname',
            #'pg_get_constraintdef(s.oid, true) as condef',
            'c.relname AS confrelname',
        ]))
        query_str.append('FROM')
        query_str.append('  pg_attribute a')
        query_str.append('JOIN pg_type t ON a.atttypid = t.oid')
        query_str.append('LEFT JOIN pg_index i ON a.attrelid = i.indrelid')
        query_str.append('  AND a.attnum = any(i.indkey)')
        query_str.append('LEFT JOIN pg_constraint s ON a.attrelid = s.conrelid')
        query_str.append('  AND s.contype = {} AND a.attnum = any(s.conkey)'.format(self.val_placeholder))
        query_str.append('LEFT JOIN pg_class c ON s.confrelid = c.oid')
        query_str.append('WHERE')
        query_str.append('  a.attrelid = {}::regclass'.format(self.val_placeholder))
        query_str.append('  AND a.attisdropped = False')
        query_str.append('  AND a.attnum > 0')
        query_str.append('ORDER BY a.attnum ASC')

        query_str = os.linesep.join(query_str)
        fields = self.query(query_str, *query_args, **kwargs)

        pg_types = {
            "float8": float,
            "timestamp": datetime.datetime,
            "int2": int,
            "int4": int,
            "int8": long,
            "numeric": decimal.Decimal,
            "text": str,
            "bpchar": str,
            "varchar": str,
            "bool": bool,
            "date": datetime.date,
            "blob": bytearray,
        }

        # the rows we can set: field_type, name, field_required, min_size, max_size,
        #   size, unique, pk, <foreign key info>
        # These keys will roughly correspond with schema.Field
        for row in fields:
            field = {
                "name": row["attname"],
                "field_type": pg_types[row["typname"]],
                "field_required": row["attnotnull"],
                "pk": bool(row["indisprimary"]),
            }

            if row["confrelname"]:
                # TODO -- I can't decide which name I like
                field["schema_table_name"] = row["confrelname"]
                field["ref_table_name"] = row["confrelname"]

            ret[field["name"]] = field

        return ret