@@ -2293,7 +2293,8 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2293
2293
char * * cmd , int * cmd_len , short * slot , void * * ctx )
2294
2294
{
2295
2295
char * key = NULL , * exp_type = NULL , * set_type = NULL ;
2296
- zval * z_value , * z_opts = NULL ;
2296
+ zend_string * ifeq = NULL , * tmp = NULL ;
2297
+ zval * z_value , * z_opts = NULL ;
2297
2298
smart_string cmdstr = {0 };
2298
2299
zend_long expire = -1 ;
2299
2300
zend_bool get = 0 ;
@@ -2312,7 +2313,6 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2312
2313
return FAILURE ;
2313
2314
}
2314
2315
2315
-
2316
2316
// Check for an options array
2317
2317
if (z_opts && Z_TYPE_P (z_opts ) == IS_ARRAY ) {
2318
2318
HashTable * kt = Z_ARRVAL_P (z_opts );
@@ -2329,11 +2329,14 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2329
2329
zend_string_equals_literal_ci (zkey , "PXAT" ))
2330
2330
) {
2331
2331
if (redis_try_get_expiry (v , & expire ) == FAILURE || expire < 1 ) {
2332
+ zend_tmp_string_release (tmp );
2332
2333
setExpiryWarning (v );
2333
2334
return FAILURE ;
2334
2335
}
2335
2336
2336
2337
exp_type = ZSTR_VAL (zkey );
2338
+ } else if (zkey && !ifeq && zend_string_equals_literal_ci (zkey , "IFEQ" )) {
2339
+ ifeq = zval_get_tmp_string (v , & tmp );
2337
2340
} else if (Z_TYPE_P (v ) == IS_STRING ) {
2338
2341
if (zend_string_equals_literal_ci (Z_STR_P (v ), "KEEPTTL" )) {
2339
2342
keep_ttl = 1 ;
@@ -2348,6 +2351,7 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2348
2351
} ZEND_HASH_FOREACH_END ();
2349
2352
} else if (z_opts && Z_TYPE_P (z_opts ) != IS_NULL ) {
2350
2353
if (redis_try_get_expiry (z_opts , & expire ) == FAILURE || expire < 1 ) {
2354
+ zend_tmp_string_release (tmp );
2351
2355
setExpiryWarning (z_opts );
2352
2356
return FAILURE ;
2353
2357
}
@@ -2356,18 +2360,28 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2356
2360
/* Protect the user from syntax errors but give them some info about what's wrong */
2357
2361
if (exp_type && keep_ttl ) {
2358
2362
php_error_docref (NULL , E_WARNING , "KEEPTTL can't be combined with EX or PX option" );
2363
+ zend_tmp_string_release (tmp );
2364
+ return FAILURE ;
2365
+ }
2366
+
2367
+ /* You can't use IFEQ with NX or XX */
2368
+ if (set_type && ifeq ) {
2369
+ php_error_docref (NULL , E_WARNING , "IFEQ can't be combined with NX or XX option" );
2370
+ zend_tmp_string_release (tmp );
2359
2371
return FAILURE ;
2360
2372
}
2361
2373
2362
2374
/* Backward compatibility: If we are passed no options except an EXPIRE ttl, we
2363
2375
* actually execute a SETEX command */
2364
2376
if (expire > 0 && !exp_type && !set_type && !keep_ttl ) {
2365
2377
* cmd_len = REDIS_CMD_SPPRINTF (cmd , "SETEX" , "klv" , key , key_len , expire , z_value );
2378
+ zend_tmp_string_release (tmp );
2366
2379
return SUCCESS ;
2367
2380
}
2368
2381
2369
2382
/* Calculate argc based on options set */
2370
- int argc = 2 + (exp_type ? 2 : 0 ) + (set_type != NULL ) + (keep_ttl != 0 ) + get ;
2383
+ int argc = 2 + (ifeq ? 2 : 0 ) + (exp_type ? 2 : 0 ) + (set_type != NULL ) +
2384
+ (keep_ttl != 0 ) + get ;
2371
2385
2372
2386
/* Initial SET <key> <value> */
2373
2387
redis_cmd_init_sstr (& cmdstr , argc , "SET" , 3 );
@@ -2379,15 +2393,22 @@ int redis_set_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
2379
2393
redis_cmd_append_sstr_long (& cmdstr , (long )expire );
2380
2394
}
2381
2395
2382
- if (set_type )
2396
+ if (ifeq ) {
2397
+ REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "IFEQ" );
2398
+ redis_cmd_append_sstr_zstr (& cmdstr , ifeq );
2399
+ } else if (set_type ) {
2383
2400
redis_cmd_append_sstr (& cmdstr , set_type , strlen (set_type ));
2401
+ }
2402
+
2384
2403
if (keep_ttl )
2385
2404
redis_cmd_append_sstr (& cmdstr , "KEEPTTL" , 7 );
2386
2405
if (get ) {
2387
2406
REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "GET" );
2388
2407
* ctx = PHPREDIS_CTX_PTR ;
2389
2408
}
2390
2409
2410
+ zend_tmp_string_release (tmp );
2411
+
2391
2412
/* Push command and length to the caller */
2392
2413
* cmd = cmdstr .c ;
2393
2414
* cmd_len = cmdstr .len ;
0 commit comments