Uploaded image for project: 'Apache Cassandra'
  1. Apache Cassandra
  2. CASSANDRA-16592

The token function in where clause return incorrect data when using token equal condition and Specified a non-exist token value

    XMLWordPrintableJSON

Details

    • Code - Bug - Unclear Impact
    • Normal
    • Normal
    • Code Inspection
    • All
    • None

    Description

      I get incorrect value when use query like 'select Token(pk1,pk2),pk1,pk2 from ks.table1 where token(pk1,pk2) = tokenValue'. The returned token value mismatch the where condition.

      This problem is reproduced in 3.11.3 and 4.0.

      Here is my schema and select statement

      // schema
      cqlsh> desc testprefix.cprefix_03 ;CREATE TABLE testprefix.cprefix_03 (
          pk1 int,
          pk2 int,
          ck1 text,
          ck2 text,
          t1 int,
          PRIMARY KEY ((pk1, pk2), ck1, ck2)
      ) WITH CLUSTERING ORDER BY (ck1 ASC, ck2 ASC)
          AND additional_write_policy = '99p'
          AND bloom_filter_fp_chance = 0.01
          AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
          AND cdc = false
          AND comment = ''
          AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
          AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
          AND crc_check_chance = 1.0
          AND default_time_to_live = 0
          AND extensions = {}
          AND gc_grace_seconds = 864000
          AND max_index_interval = 2048
          AND memtable_flush_period_in_ms = 0
          AND min_index_interval = 128
          AND read_repair = 'BLOCKING'
          AND speculative_retry = '99p';
      
      
      

      execute cql query

      // code placeholder
      cqlsh> SELECT Token(pk1,pk2), pk1,pk2  from testprefix.cprefix_03 WHERE  token(pk1, pk2) =-9223372036854775808 LIMIT 2; 
      system.token(pk1, pk2) | pk1    | pk2
      ------------------------+--------+---------
         -9222849988925915479 | 394560 | 3394560
         -9222849988925915479 | 394560 | 3394560
      (2 rows)
      
      cqlsh> SELECT Token(pk1,pk2) from testprefix.cprefix_03 where pk1 = 394560 and pk2 = 3394560 LIMIT 2; 
      system.token(pk1, pk2)
      ------------------------
         -9222849988925915479
         -9222849988925915479
      (2 rows)
      
      cqlsh> SELECT Token(pk1,pk2), pk1,pk2  from testprefix.cprefix_03 WHERE  token(pk1, pk2) =-9222849988925915479 LIMIT 2; 
      system.token(pk1, pk2) | pk1    | pk2
      ------------------------+--------+---------
         -9222849988925915479 | 394560 | 3394560
         -9222849988925915479 | 394560 | 3394560
      (2 rows)

      we can find  that token value in the condition  are inconsistent with the values in the result.

      --------------------------------------------------------------------------------------------

      Then review the source code, to seek the anwser. 

      // code placeholder
      private static void addRange(SSTableReader sstable, AbstractBounds<PartitionPosition> requested, List<AbstractBounds<PartitionPosition>> boundsList)
      {
          if (requested instanceof Range && ((Range)requested).isWrapAround())    //  first condition
          {
              if (requested.right.compareTo(sstable.first) >= 0)
              {
                  // since we wrap, we must contain the whole sstable prior to stopKey()
                  Boundary<PartitionPosition> left = new Boundary<PartitionPosition>(sstable.first, true);
                  Boundary<PartitionPosition> right;
                  right = requested.rightBoundary();
                  right = minRight(right, sstable.last, true);
                  if (!isEmpty(left, right))
                      boundsList.add(AbstractBounds.bounds(left, right));
              }
              if (requested.left.compareTo(sstable.last) <= 0)
              {
                  // since we wrap, we must contain the whole sstable after dataRange.startKey()
                  Boundary<PartitionPosition> right = new Boundary<PartitionPosition>(sstable.last, true);
                  Boundary<PartitionPosition> left;
                  left = requested.leftBoundary();
                  left = maxLeft(left, sstable.first, true); // second condition
                  if (!isEmpty(left, right))
                      boundsList.add(AbstractBounds.bounds(left, right));
              }
          }
          else
          {
              assert requested.left.compareTo(requested.right) <= 0 || requested.right.isMinimum();
              Boundary<PartitionPosition> left, right;
              left = requested.leftBoundary();
              right = requested.rightBoundary();
              left = maxLeft(left, sstable.first, true);
              // apparently isWrapAround() doesn't count Bounds that extend to the limit (min) as wrapping
              right = requested.right.isMinimum() ? new Boundary<PartitionPosition>(sstable.last, true)
                                                      : minRight(right, sstable.last, true);
              if (!isEmpty(left, right))
                  boundsList.add(AbstractBounds.bounds(left, right));
          }
      }
      
      • we use token equal ,so isWrapAround is true.
      • requestd.left = requestd.right = -9223372036854775808,
      • the real sst dataBoundary.left = -9222849988925915479
      • so the maxLeft return the real dataBoudary.left. We get the incorrect  data

       

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              cimon cimon
              Ekaterina Dimitrova, Michael Semb Wever
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: