578 Commits

Author SHA1 Message Date
michael-grunder
e9e9e49509 Add maxRetries to redis_sock_configure.
This lets users configure `maxRetries` with `RedisSentinel`

Fixes #2700
2025-09-12 09:32:02 -07:00
michael-grunder
35df8ad7c2 Attempt to fix an overflow bug in ZADD on Windows
Theory: In 64 bit windows `long` is 32 bits wide meaning that using a
long to append `ZADD` scores can truncate.

Possible fix for #2697
2025-09-09 16:30:43 -07:00
Michael Grunder
d0b0c5cfdd Fix typo
Co-authored-by: Pavlo Yatsukhnenko <yatsukhnenko@users.noreply.github.com>
2025-09-01 09:41:12 -07:00
michael-grunder
b8de91c9e0 Fix errors and a warning
* PHP < 8.0 took a `char*` as `php_json_decode` input, whereas newer
  versions take a const char * so ifdef around this.

* Fix compilation errors due to `false` not being defined. So as to make
  a minimal change we can just use 0 and 1
2025-09-01 09:41:12 -07:00
michael-grunder
d80b725824 Implement VGETATTR command 2025-09-01 09:41:12 -07:00
michael-grunder
7f9b1f416e Implement VLINKS command 2025-09-01 09:41:12 -07:00
michael-grunder
1deca62841 Implement VRANDMEMBER
`VRANDMEMBER` has the exact same semantics of `SRANDMEMBER` so make
`SRANDMEMBER` a keyword based command and use it for `VRANDMEMBER`.

See #2543
2025-09-01 09:41:12 -07:00
michael-grunder
96378b70fd Implement VEMB and slightly rework VINFO
Unfortunately `VEMB` has a unique `RESP2` reply as far as I can tell,
where it sends the embedding mode (int8, bin, fp32) as a simple string.

This would cause any of PhpRedis' generic reply handlers to turn that
into `true` which isn't useful. For that reason we need a custom reply
handler.

Additionally slightly rework `VINFO` to short circuit and return failure
if we read anything other than a bulk string or an integer reply type.
Otherwise we may get out of sync on the socket.

See #2543
2025-09-01 09:41:12 -07:00
michael-grunder
0fda9f293b Implement VCARD, VDIM, and VINFO
All of these commands have the same form `<cmd> key`. `VINFO` is a bit
of an outlier however that uses simple strings as opposed to bulk
strings for the key names, meaning we had to create a custom handler.

See #2543
2025-09-01 09:41:12 -07:00
michael-grunder
0ed0fc0562 Add Redis::REDIS_VECTORSET type.
Redis >= 8.0 has a new type `vectorset` that we should support like all
the other types.
2025-08-28 09:34:07 -07:00
michael-grunder
03837f0230 Remove pointless casts
You never have to explicitly cast between `void*` and any other pointer
type.
2025-08-21 08:53:51 -07:00
michael-grunder
8be2306e4f Fix several issues surfaced by gcc -fanzlyze
Mostly null pointer derefs or use of uninitialized values. Some were
probably false positives since hte analyzer can't fully reason about how
the zend internals use `zval` structs but the fixes don't really have
any downside.
2025-08-15 07:52:21 -07:00
michael-grunder
340f23b082 Fix an off-by-one length calculation error.
We want `buf + 1`, `len - 1`.
2025-07-26 22:24:43 -07:00
michael-grunder
2acab399cb Fix the echo liveness check when in sentinel mode.
The current echo liveness check was doing one big complex conditional
trying to incorporate both sentinel's expected ERR no such command
response and non-sentinel's actual bulk reply to ECHO.

This commit refactors the logic to check the echo response into a little
helper with different logic depending on whether or not we're connected
to a sentinel.

Additionally, we add a test to verify that we are in fact reusing
persistent connections when the user requests a persistent connection
with `RedisSentinel`.

Fixes #2148
2025-07-18 08:43:22 -07:00
Michael Grunder
ce5b0facc2 Implement HGETEX, HSETEX, HGETDEL, and refactor HMGET (#2667)
* Rework HMGET and implement HGETEX

Instead of using a bespoke NULL terminated `zval**` array for the
context array we can use a `HashTable`. This might be a tiny bit more
expensive but Zend hashtables are quite efficient and this should also
be less error prone.

* Rework our `HashTable` context array to store keys

Instead of sending an array of values we can instead add the fields as
keys to our context array. That way when we combine the keys with the
Redis provided values we can do it in-place and then just give the
HashTable to the user to then do with what they want.

* Implement HGETDEL command.

* Fix edge cases to abide by legacy behavior.

Previously we coerced integer strings into integer keys when zipping
`HMGET` responses. This commit adds logic so we continue to do this and
do not change semantics.

* Implement `HGETDEL` and `HGETEX` for `RedisCluster`.

This commit implements the new commands and reworks the `HMGET` reply
handler to use the new context `HashTable`.

* Fix an edge case where we get zero multiblk elements

* Tests for `HGETEX` and `HGETDEL`

* Minor logic improvement

We don't need to check if `c->reply_len > 0` in the last else block
since we have already determined it must be.

* Implement `HSETEX` for `Redis` and `RedisCluster`

* Use `zval_get_tmp_string` ro populating non-long keys
2025-07-16 16:46:09 -07:00
michael-grunder
7350768cd9 Implement several hash expiration commands
Commands implemented:

`H[P]EXPIRE`
`H[P]TTL`
`H[P]EXPIREAT`
`H[P]EXPIRETIME`
`HPERSIST`
2025-05-07 08:16:14 -07:00
michael-grunder
593ba012ac Check for dragonfly_version in HELLO response
DragonflyDB will report to be Redis but also include `dragonfly_version`
in the hello response, which we can use to identify the fork.

Also fix parsing of the `HELLO` response for `serverName()` and
`serverVersion()`. Starting in Redis 8.0 there seem to always be modules
running, which the previous function was not expecting or parsing.
2025-05-05 09:31:11 -07:00
Jakub Onderka
614b86e457 New macros REDIS_RESPONSE_ERROR and REDIS_RETURN_ZVAL
Deduplicate code that is used in many methods. Also optimise adding new element to array in pipeline mode and returning zval in atomic mode
2025-04-05 09:05:26 -07:00
Jakub Onderka
0a85bd824a Simplify redis_unpack method calling
This method always unpack given string to zval, so it is not necessary to check output value
2025-04-02 13:02:52 -07:00
Michael Grunder
0445e683e7 Refactor getWithMeta logic (#2643)
* Refactor `getWithMeta`

* Consolidate `getWithMeta()` test.

* Review comments
2025-03-31 12:42:29 -07:00
Jakub Onderka
4f6a3ed1e7 New option 'database' for Redis class constructor (#2597)
* New option 'database' for Redis class constructor

Selecting database is very common action after connecting to Redis. This simplifies lazy connecting to Redis, when requested database will be selected after first command.

* More specific exception message when invalid auth or database number is provided

Before it was just 'Redis server went away'

* Rename reselect_db method to redis_select_db and slightly optimise it
2025-03-26 18:05:33 -07:00
Pavlo Yatsukhnenko
cbaf095ff7 Allow calling methods only in atomic mode 2025-03-20 10:38:56 -07:00
Pavlo Yatsukhnenko
056c2dbee7 Introduce Redis::serverName and Redis::serverVersion methods
Right now we can't implement `HELLO` command to switch protocol
because we don't support new reply types that come with RESP3.
But we can use `HELLO` reply to expose some server information.
2025-03-20 10:38:56 -07:00
michael-grunder
e73130fee0 Fix error length calculation + UB sanity check.
For an error reply we're starting at `buf + 1` so we want `len - 1`. As
a sanity check we now return early if `len < 1`.

Also, make certain that len > 2 for our special detection of `*-1` since
we're doing `memcmp(buf + 1, "-1", 2);`
2025-03-11 09:38:41 -07:00
Pavlo Yatsukhnenko
9036ffca6a Add getWithMeta method 2025-02-25 16:27:10 +02:00
michael-grunder
29e5cf0d8c Minor refactor of ignroe numbers option
* We want to run the logic if either a serializer OR a compression
  option is set.
* IEE754 doubles can theoretically have a huge number of characters.
2025-02-05 14:12:42 -08:00
michael-grunder
f9ce9429ef Introduce Redis::OPT_PACK_IGNORE_NUMBERS option.
Adds an option that instructs PhpRedis to not serialize or compress
numeric values. Specifically where `Z_TYPE_P(z) == IS_LONG` or
`Z_TYPE_P(z) == IS_DOUBLE`.

This flag lets the user enable serialization and/or compression while
still using the various increment/decrement command (`INCR`, `INCRBY`,
`DECR`, `DECRBY`, `INCRBYFLOAT`, `HINCRBY`, and `HINCRBYFLOAT`).

Because PhpRedis can't be certain that this option was enabled when
writing keys, there is a small runtime cost on the read-side that tests
whether or not the value its reading is a pure integer or floating point
value.

See #23
2025-02-05 14:12:42 -08:00
Bentley O'Kane-Chase
044b30386f Reduce buffer size for signed integer, strlen(-9223372036854775808) = 20 + 1 for '\0' 2024-12-17 17:08:36 -08:00
Bentley O'Kane-Chase
35c5988027 Formatting improvements 2024-12-17 17:08:36 -08:00
Bentley O'Kane-Chase
138d07b67c Print cursor as unsigned 64 bit integer 2024-12-17 17:08:36 -08:00
michael-grunder
42a427695e Use defines for callback growth + sanity check
See #2595
2024-12-10 09:51:49 -08:00
Jakub Onderka
a551fdc94c Switch from linked list to growing array for reply callbacks
Reduce allocation and deallocation count and also memory usage when using pipelining
2024-12-09 10:40:39 -08:00
Jakub Onderka
be38856205 Reuse redis_sock_append_auth method
In library.c, there are currently two methods for constructing AUTH command, so we can reuse code from redis_sock_append_auth also in redis_sock_auth_cmd method
2024-12-01 11:44:53 -08:00
Jakub Onderka
571ffbc8e0 Switch pipeline_cmd from smart_str to smart_string
As we don't need to extract zend_string from pipeline_cmd, we can use simple smart_string structure
2024-12-01 11:39:55 -08:00
Jakub Onderka
7895636a3a Remove unused redis_debug_response method from library.c 2024-11-27 11:25:05 -08:00
Jakub Onderka
2434ba294c Optimise HMGET method
Allocate output array to expected size and reuse already allocated string for output array keys
2024-11-27 10:33:42 -08:00
Jakub Onderka
f6906470a5 Use zval_get_tmp_string method that is faster when provided zval is string 2024-11-26 18:28:09 -08:00
Jakub Onderka
2a2f908f2b Optimise constructing Redis command string
Instead of snprintf method, use zend_print_long_to_buf that can be inlined
2024-11-26 17:20:11 -08:00
Jakub Onderka
400503b871 Optimise method array_zip_values_and_scores
Initialize array with know size and reuse already allocated keys
2024-11-26 10:39:23 -08:00
Jakub Onderka
3a2f3f45fc Use immutable empty array in Redis::hKeys 2024-11-26 10:39:23 -08:00
Jakub Onderka
64da891e6f Do not allocate empty string or string with one character
From PHP 8, empty strings or string with one character don't need to be allocated. This change will reduce memory usage.
2024-11-26 10:39:23 -08:00
Jakub Onderka
99beb9221c Initialize arrays with known size
We know in advance the array size, so it makes sense to avoid reallocation when adding new elements. Also use immutable empty array in when we know in advance that redis will return zero elements.
2024-11-26 10:39:23 -08:00
Jakub Onderka
b665925eed Use smart str for constructing pipeline cmd 2024-11-25 09:41:27 -08:00
michael-grunder
085d61ecfb Create a strncmp wrapper
On some glibc implementations strncmp is a macro. This commit simply creates a
`redis_strncmp` static inline wrapper function so we can `ZEND_STRL` instead of
manually counting the length or using `sizeof(s)-1` each time.

Fixes #2565
2024-10-15 10:40:15 -07:00
Remi Collet
37cebdd70b cleanup code for unsupported versions 2024-08-05 08:58:58 -07:00
michael-grunder
7de29d57d9 Fix a macOS (M1) compiler warning. 2024-07-08 20:50:06 -07:00
Michael Grunder
7050c98909 Play around with more ZEND_STRL usage (#2505)
* Play around with more ZEND_STRL usage

* strncasecmp is a macro on Windows
2024-06-15 14:48:30 -07:00
michael-grunder
f8c762e70b Use ZEND_STRL where appropriate.
Use the `ZEND_STRL` macro in several places rather than manually sending
a static string and its length as a constant.
2024-06-01 13:41:26 -07:00
michael-grunder
c139de3aba We don't need to use a ranom value for our ECHO liveness challenge.
A microsecond resolution timestamp combined with a monotonically
incremented counter should be sufficient.

This also fixes PHP 8.4 compilation as PHP 8.4 doesn't seem to have
`php_rand()`.
2024-06-01 13:41:26 -07:00
michael-grunder
d9c48b788d KeyDB: Get our tests passing against KeyDB.
This commit fixes our unit tests so they also pass against the KeyDB
server.  We didn't ned to change all that much.  Most of it was just
adding a version/keydb check.

The only change to PhpRedis itself was to relax the reply requirements
for XAUTOCLAIM.  Redis 7.0.0 added a third "these elements were recently
removed" reply which KeyDB does not have.

Fixes #2466
2024-03-22 07:47:43 -07:00