Hi Mike,
When using Core, we can do a bulk insert and bulk return with Postgresql trivially:
    from sqlalchemy import table, column
    t = table('foo', column('id'), column('bar')
    ins = t.insert().values([{'bar': 'a'}, {'bar': 'b'}]).returning(
foo.id)
    results = conn.execute(ins)
    
    ids = results.fetchall()
However, with raw textual SQL, it is a bit more inconvenient.
The following doesn't work:
    results = conn.execute(text(
        'insert into foo values (:bar) returning id
    ), [{'bar': 'a'}, {'bar': 'b'}])
    
    # raises sqlalchemy.exc.ResourceClosedError: This result object does not return rows. It has been closed automatically.
    results.fetchall()
To get it working, we have to do it this way:
    results = conn.execute(text(
        'insert into foo values (:bar0), (:bar1)
    ), {'bar0': 'x', 'bar1': 'y'})
    assert results.fetchall()
This isn't convenient. For example you would have to convert a list of bars like [{'bar': 'a'}, {'bar': 'b'}] into a single dict with uniquely name keys {'bar0': 'a', 'bar1': 'b'}.
I imagine sqlalchemy is doing that under the hood when using core. Is there some convenience function available in sqlalchemy core that I can use to simplify this?