scassandra / scassandra-server

Stubbed Cassandra
http://www.scassandra.org
Other
87 stars 34 forks source link

Map vs ListMap #189

Closed Alien2150 closed 2 years ago

Alien2150 commented 7 years ago

See https://github.com/scassandra/scassandra-server/issues/188 Feedback appreciated

tolbertam commented 7 years ago

Awesome, thanks for looking into this @Alien2150 !

It looks like travis is failing to compile the project because ListMap isn't imported, although I could have sworn that wasn't needed (maybe it's globally imported in 2.12 but not 2.11?) I'll look into it and let you know.

tolbertam commented 7 years ago

It looks like just a few missing imports, there's also another change needed in PrimingJsonImplicits so spray knows how to marshal ListMap i'll push something up for this.

tolbertam commented 7 years ago

Hrmm, I just wrote a test around this and I noticed that Scassandra was already maintaining the order of entries provided from json into the serialized Map.

In your issue you mentioned this logging statement:

[debug] - org.apache.http.wire - http-outgoing-0 >> "{"when":{"query":"SELECT user_id, used from TOKENS"},"then":{"variable_types":[],"rows":[{"user_id":"b94133a3-e35d-4c94-9463-d806a64afd71", "used":false}],"column_types":{"user_id":"ascii","used":"boolean"}}}"

and that user_id and used were transposed.

Looking at this logging statement, it's coming from the java-client library, not from server. It looks like if you use an insertion order map implementation like LinkedHashMap or ImmutableList in java (or ListMap in scala) when priming it works

Since you mentioned using quill, is it possible that you are creating a scala Map as input, but then converting into a java map and that does not maintain that order during the conversion?

tolbertam commented 7 years ago

For context, here was my test:

    @Test
    public void columnIndexOrderInResult() {
        //given
        String query = "select * from people where name = ?";

        // doesn't work - HashMap is not insertion ordered.
        /* Map<String, String> row0 = new HashMap<>();
        row0.put("name", "Chris");
        row0.put("color", "blue");
        row0.put("planet", "earth"); */

        // works - ImmutableMap is insertion ordered.
        Map<String, ?> row0 = ImmutableMap.of("name", "Chris", "color", "blue", "planet", "earth");
        Map<String, ?> row1 = ImmutableMap.of("name", "John", "color", "green", "planet", "saturn");
        List<Map<String, ?>> rows = ImmutableList.of(row0, row1);
        primingClient.primePreparedStatement(preparedStatementBuilder()
                .withQuery(query)
                .withRows(rows)
                .build());

        //when
        CassandraResult results = cassandra().prepareAndExecute(query, "Chris");

        //then
        List<CassandraRow> asList = results.rows();
        assertEquals(2, asList.size());
        assertEquals("Chris", asList.get(0).getString(0));
        assertEquals("blue", asList.get(0).getString(1));
        assertEquals("earth", asList.get(0).getString(2));
        assertEquals("John", asList.get(1).getString(0));
        assertEquals("green", asList.get(1).getString(1));
        assertEquals("saturn", asList.get(1).getString(2));
    }
Alien2150 commented 7 years ago

will try that one out. Thanks