Implements ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREMRANGEBYLEX commands. */
| 1888 | |
| 1889 | /* Implements ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZREMRANGEBYLEX commands. */ |
| 1890 | void zremrangeGenericCommand(client *c, zrange_type rangetype) { |
| 1891 | robj *key = c->argv[1]; |
| 1892 | robj *zobj; |
| 1893 | int keyremoved = 0; |
| 1894 | unsigned long deleted = 0; |
| 1895 | zrangespec range; |
| 1896 | zlexrangespec lexrange; |
| 1897 | long start, end, llen; |
| 1898 | const char *notify_type = NULL; |
| 1899 | |
| 1900 | /* Step 1: Parse the range. */ |
| 1901 | if (rangetype == ZRANGE_RANK) { |
| 1902 | notify_type = "zremrangebyrank"; |
| 1903 | if ((getLongFromObjectOrReply(c,c->argv[2],&start,NULL) != C_OK) || |
| 1904 | (getLongFromObjectOrReply(c,c->argv[3],&end,NULL) != C_OK)) |
| 1905 | return; |
| 1906 | } else if (rangetype == ZRANGE_SCORE) { |
| 1907 | notify_type = "zremrangebyscore"; |
| 1908 | if (zslParseRange(c->argv[2],c->argv[3],&range) != C_OK) { |
| 1909 | addReplyError(c,"min or max is not a float"); |
| 1910 | return; |
| 1911 | } |
| 1912 | } else if (rangetype == ZRANGE_LEX) { |
| 1913 | notify_type = "zremrangebylex"; |
| 1914 | if (zslParseLexRange(c->argv[2],c->argv[3],&lexrange) != C_OK) { |
| 1915 | addReplyError(c,"min or max not valid string range item"); |
| 1916 | return; |
| 1917 | } |
| 1918 | } else { |
| 1919 | serverPanic("unknown rangetype %d", (int)rangetype); |
| 1920 | } |
| 1921 | |
| 1922 | /* Step 2: Lookup & range sanity checks if needed. */ |
| 1923 | if ((zobj = lookupKeyWriteOrReply(c,key,shared.czero)) == NULL || |
| 1924 | checkType(c,zobj,OBJ_ZSET)) goto cleanup; |
| 1925 | |
| 1926 | if (rangetype == ZRANGE_RANK) { |
| 1927 | /* Sanitize indexes. */ |
| 1928 | llen = zsetLength(zobj); |
| 1929 | if (start < 0) start = llen+start; |
| 1930 | if (end < 0) end = llen+end; |
| 1931 | if (start < 0) start = 0; |
| 1932 | |
| 1933 | /* Invariant: start >= 0, so this test will be true when end < 0. |
| 1934 | * The range is empty when start > end or start >= length. */ |
| 1935 | if (start > end || start >= llen) { |
| 1936 | addReply(c,shared.czero); |
| 1937 | goto cleanup; |
| 1938 | } |
| 1939 | if (end >= llen) end = llen-1; |
| 1940 | } |
| 1941 | |
| 1942 | /* Step 3: Perform the range deletion operation. */ |
| 1943 | if (zobj->encoding == OBJ_ENCODING_ZIPLIST) { |
| 1944 | switch(rangetype) { |
| 1945 | case ZRANGE_AUTO: |
| 1946 | case ZRANGE_RANK: |
| 1947 | zobj->m_ptr = zzlDeleteRangeByRank((unsigned char*)zobj->m_ptr,start+1,end+1,&deleted); |
no test coverage detected