def METHOD_NAME(curs, table, pkey, row):
    # TODO: check that these always return in order
    columns = list(row.keys())
    vals = list(map(lambda v: None if v == '' else v, row.values()))
    now = datetime.now()
    # Append create and update timestamp
    columns.append('last_updated')
    vals.append(now)
    columns.append('created')
    vals.append(now)
    # These are used for update; remove the pkey!
    nonkeys = list(filter(lambda col: col not in pkey, columns))
    # Remove create timestamp
    toupdate = nonkeys[:-1]
    if len(toupdate) > 1:
        qry = f'''
        INSERT INTO "{table}" ({", ".join(map(lambda col: f'"{col}"', columns))})
        VALUES ({", ".join(['%s'] * len(vals))})
        ON CONFLICT ({", ".join(map(lambda col: f'"{col}"', pkey))})
        DO UPDATE
            SET ({", ".join(map(lambda col: f'"{col}"', toupdate))}) = ({", ".join(map(lambda col: f'EXCLUDED."{col}"', toupdate))})
            WHERE {" OR ".join(map(lambda col: f'("{table}"."{col}" IS NULL AND EXCLUDED."{col}" IS NOT NULL) OR ("{table}"."{col}" IS NOT NULL AND EXCLUDED."{col}" IS NULL) OR ("{table}"."{col}" != EXCLUDED."{col}")', toupdate[:-1]))}
        '''
    else:
        qry = f'''
        INSERT INTO "{table}" ({", ".join(map(lambda col: f'"{col}"', columns))})
        VALUES ({", ".join(['%s'] * len(vals))})
        ON CONFLICT ({", ".join(map(lambda col: f'"{col}"', pkey))})
        DO NOTHING
        '''
    curs.execute(qry, vals)