File: response_transformers.tcl

package info (click to toggle)
redis 5%3A8.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 21,920 kB
  • sloc: ansic: 217,146; tcl: 51,883; sh: 4,625; perl: 4,214; cpp: 3,568; python: 3,165; makefile: 2,055; ruby: 639; javascript: 30; csh: 7
file content (110 lines) | stat: -rw-r--r-- 3,859 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# Tcl client library - used by the Redis test
#
# Copyright (C) 2009-Present, Redis Ltd.
# All Rights reserved.
#
# Licensed under your choice of (a) the Redis Source Available License 2.0
# (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
# GNU Affero General Public License v3 (AGPLv3).
#
# This file contains a bunch of commands whose purpose is to transform
# a RESP3 response to RESP2
# Why is it needed?
# When writing the reply_schema part in COMMAND DOCS we decided to use
# the existing tests in order to verify the schemas (see logreqres.c)
# The problem was that many tests were relying on the RESP2 structure
# of the response (e.g. HRANDFIELD WITHVALUES in RESP2: {f1 v1 f2 v2}
# vs. RESP3: {{f1 v1} {f2 v2}}).
# Instead of adjusting the tests to expect RESP3 responses (a lot of
# changes in many files) we decided to transform the response to RESP2
# when running with --force-resp3

package require Tcl 8.5

namespace eval response_transformers {}

# Transform a map response into an array of tuples (tuple = array with 2 elements)
# Used for XREAD[GROUP]
proc transfrom_map_to_tupple_array {argv response} {
    set tuparray {}
    foreach {key val} $response {
        set tmp {}
        lappend tmp $key
        lappend tmp $val
        lappend tuparray $tmp
    }
    return $tuparray
}

# Transform an array of tuples to a flat array
proc transfrom_tuple_array_to_flat_array {argv response} {
    set flatarray {}
    foreach pair $response {
        lappend flatarray {*}$pair
    }
    return $flatarray
}

# With HRANDFIELD, we only need to transform the response if the request had WITHVALUES
# (otherwise the returned response is a flat array in both RESPs)
proc transfrom_hrandfield_command {argv response} {
    foreach ele $argv {
        if {[string compare -nocase $ele "WITHVALUES"] == 0} {
            return [transfrom_tuple_array_to_flat_array $argv $response]
        }
    }
    return $response
}

# With some zset commands, we only need to transform the response if the request had WITHSCORES
# (otherwise the returned response is a flat array in both RESPs)
proc transfrom_zset_withscores_command {argv response} {
    foreach ele $argv {
        if {[string compare -nocase $ele "WITHSCORES"] == 0} {
            return [transfrom_tuple_array_to_flat_array $argv $response]
        }
    }
    return $response
}

# With ZPOPMIN/ZPOPMAX, we only need to transform the response if the request had COUNT (3rd arg)
# (otherwise the returned response is a flat array in both RESPs)
proc transfrom_zpopmin_zpopmax {argv response} {
    if {[llength $argv] == 3} {
        return [transfrom_tuple_array_to_flat_array $argv $response]
    }
    return $response
}

set ::trasformer_funcs {
    XREAD transfrom_map_to_tupple_array
    XREADGROUP transfrom_map_to_tupple_array
    HRANDFIELD transfrom_hrandfield_command
    ZRANDMEMBER transfrom_zset_withscores_command
    ZRANGE transfrom_zset_withscores_command
    ZRANGEBYSCORE transfrom_zset_withscores_command
    ZRANGEBYLEX transfrom_zset_withscores_command
    ZREVRANGE transfrom_zset_withscores_command
    ZREVRANGEBYSCORE transfrom_zset_withscores_command
    ZREVRANGEBYLEX transfrom_zset_withscores_command
    ZUNION transfrom_zset_withscores_command
    ZDIFF transfrom_zset_withscores_command
    ZINTER transfrom_zset_withscores_command
    ZPOPMIN transfrom_zpopmin_zpopmax
    ZPOPMAX transfrom_zpopmin_zpopmax
}

proc ::response_transformers::transform_response_if_needed {id argv response} {
    if {![::redis::should_transform_to_resp2 $id] || $::redis::readraw($id)} {
        return $response
    }

    set key [string toupper [lindex $argv 0]]
    if {![dict exists $::trasformer_funcs $key]} {
        return $response
    }

    set transform [dict get $::trasformer_funcs $key]

    return [$transform $argv $response]
}