3419 Commits

Author SHA1 Message Date
Pavlo Yatsukhnenko 334937cb98 Add PHP 8.5 to CI 2025-08-04 07:39:25 -07:00
michael-grunder d1d690053f Implement VSIM command
This command is similar to `VADD` in that it's pretty simple but allows
for a great many options.

In it's most basic form:

```php
// To get similarity of a different element
$redis->vsim('myvec', 'some-element');

// To get similarity for a vector of scores
```

As seen above the method attempts to infer element or vector from the
argument passed to $member`. However, since we do serialize the member
when doing `ELE` mode, the user can also specify `ELE` explicitly in the
options array to force an `ELE` search sending serialized values.

```php
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$redis->vsim('myvec', [3.14, 2.71], ['ELE']);
```

See #2543
2025-07-31 08:30:47 -07:00
michael-grunder 286fa63064 Implement VADD command
This is for Redis 8.0's vector sets.

The command itself can be quite complex with all of the various options but
pretty simple using all defaults.

```php
$redis->vadd('myvec', [3.14, 2.17], 'myelement');
```

The implementation takes a default argument `$options` which can be an array in
order to specify the myriad of other knobs users can send. We just do a bit of
validation on inputs (e.g. certain numeric options must be positive) and make
sure the command is constructed in a valid way (e.g. REDUCE <dim> must come
before the floating point values).

By default we deliver `FP32` blobs but allow the user to send `VALUES` in the
options array which will cause PhpRedis to send N individual values. Sending
values is slower but might be nice for debugging (e.g. watching monitor)

See #2543
2025-07-31 00:57:28 -07:00
Wyatt OʼDay 9cae7815da Make changes requested by @yatsukhnenko 2025-07-30 09:37:32 -07:00
Wyatt OʼDay d18db84c68 Link to the correct header 2025-07-30 09:37:32 -07:00
Wyatt OʼDay 1e6f5477cb Fix compiling with PHP 8.5.0 alpha3 and newer 2025-07-30 09:37:32 -07:00
michael-grunder ca80ee0e67 Fix passing NULL for hash expiry argument
The stubs specify `?string $mode = NULL` but we were using `Z_PARAM_STR`
causing an arginfo mismatch.

Fixes #2674
2025-07-28 10:33:49 -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
Pavlo Yatsukhnenko a6922a07fe Update redis_commands.c
Co-authored-by: Michael Grunder <michael.grunder@gmail.com>
2025-07-24 09:38:01 -07:00
Pavlo Yatsukhnenko 6b2f088d49 Fix hset fields handling 2025-07-24 09:38:01 -07:00
Pavlo Yatsukhnenko 7805da7542 Fix HSetEx expiry argument handling 2025-07-24 09:08:33 -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 75acbb0984 Remove unused macros + simplify some logic 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
Anton Smirnov 8dada174c4 Add an INI setting returning 5.x legacy behavior -- readonly session on lock failure 2025-07-09 20:07:57 -07:00
michael-grunder 152fdda9b1 Fix double -> int truncation warning 2025-05-08 09:19:12 -07:00
michael-grunder 8014000369 Attempt to fix flaky GitHub CI tests.
We often have to rerun the test suite on GitHub actions because of a
hard to reproduce "Read error on connection" exception when getting a
new `RedisCluster` instance.

No one has ever reported this failure outside of GitHub CI and it's not
clear exactly what might be going on.

This commit does two main things:

1. Allows for one failure to construct a new `RedisCluster` instance but
   only if we detect we're running in GitHub CI.

2. Adds much more diagnostic information if we still have a fatal error
   (e.g. we can't connect in two tries, or some other fatal error
   happens). The new info includes the whole callstack before aborting
   as well as an attempt to manually ping the seeds with `redis-cli`.
2025-05-08 09:19:12 -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
michael-grunder b48aa0d471 Fix an unused variable warning 2025-04-20 10:18:30 -07:00
AkameOuO b7a97e5ec3 Update README.md 2025-04-20 09:38:11 -07:00
Michael Giuffrida bfbab89258 Broaden return type for Redis::hGetAll
`Redis::hGetAll()` returns an array indexed by `string`s and/or `int`s depending on the values in the hash set.

The function in the PHP stub was annotated as though the array were keyed only by strings, which is tighter than reality.
2025-04-20 09:03:22 -07:00
Rory 3c64b33ffe Fix SIGABRT in PHP 8.4 with RedisArray
Same fix as 6e5360d1, with PHP switching from `ZEND_ASSUME` to `ZEND_ASSERT` in zend_hash_str_update_ptr.

Fixes #2648
2025-04-08 09:38:45 -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
michael-grunder 5208818e8c We can use zval_get_tmp_string here 2025-04-02 13:02:52 -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 60ca48f3ce Redis Cluster does not have SELECT. (#2644) 2025-04-01 11:33:44 -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
Remi Collet 3828c9293b cleanup session temp file (#2641)
* cleanup session temp file

* Fix Deprecated: Automatic conversion of false to array
2025-03-26 15:25:22 -07:00
michael-grunder 52e2b8a788 Prepare for 6.2.0 release 2025-03-24 12:06:17 -07:00
michael-grunder 300c5fb218 Make execHello protected
This lets a subclass override it
2025-03-21 11:23:58 -07:00
michael-grunder fa3eb00683 Add tests for serverName() and serverVersion() 2025-03-20 14:18:44 -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
Pavlo Yatsukhnenko f73f5fcce5 Fix arguments order for SET command
Redis and Valkey doesn't consider command as invalid if order of arguments
is changed but other servers like DragonflyDB does.
In this commit `SET` command is fixed to more strictly follow the specs.
Also fixed usage of `zend_tmp_string` for `ifeq` argument.
2025-03-16 12:10:53 -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
michael-grunder d342e4ac18 Implement GETDEL for RedisCluster
Fixes #2629
2025-03-06 10:06:26 -08:00
Pavlo Yatsukhnenko 36ab585039 Merge pull request #2627 from phpredis/feature/with-meta
Add `getWithMeta` method
2025-02-26 16:53:48 +02:00
Pavlo Yatsukhnenko 807f806fe8 Reorganize tests 2025-02-25 17:40:23 +02:00
Pavlo Yatsukhnenko 1b72964e39 Update CHANGELOG.md 2025-02-25 16:27:39 +02:00
Pavlo Yatsukhnenko 9036ffca6a Add getWithMeta method 2025-02-25 16:27:10 +02:00
michael-grunder abb0f6ccc8 Add details to the option doc block 2025-02-05 14:12:42 -08: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
Pavlo Yatsukhnenko 41e114177a Merge pull request #2618 from phpredis/codeql-v3
Update codeql to v3
2025-02-01 20:20:21 +02:00
Pavlo Yatsukhnenko a10bca35bb Update codeql to v3 2025-01-31 22:07:21 +02:00
James Kennedy c7b8784310 Invalidate slot cache on failed cluster connections 2025-01-20 15:34:53 -08:00
michael-grunder a2eef77f44 Implement Valkey >= 8.1 IFEQ set option
Implement the new `IFEQ` `SET` option that will be included in `Valkey`
8.1.

See: valkey-io/valkey#1324
2025-01-20 08:04:27 -08:00
michael-grunder faa4bc2086 Don't cast a uint64_t to a long.
We recently updated PhpRedis to handle `SCAN` cursors > 2^63 as strings
(as internally PHP integers are longs).

However, the `redis_build_scan_cmd` took the cursor as a long, which
would overflow if the value was > `2^63`.

This commit simply changes the function to take a `uint64_t` and call
our specific `redis_append_sstr_u64` so we send the cursor to Redis
correctly.

Fixes #2454.
2025-01-13 12:13:44 -08:00