@@ -65,6 +65,13 @@ typedef struct redisLcsOptions {
6565 zend_bool withmatchlen ;
6666} redisLcsOptions ;
6767
68+ typedef struct redisRestoreOptions {
69+ zend_bool replace ;
70+ zend_bool absttl ;
71+ zend_long idletime ;
72+ zend_long freq ;
73+ } redisRestoreOptions ;
74+
6875/* Local passthrough macro for command construction. Given that these methods
6976 * are generic (so they work whether the caller is Redis or RedisCluster) we
7077 * will always have redis_sock, slot*, and */
@@ -2411,6 +2418,100 @@ int redis_lcs_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
24112418 return SUCCESS ;
24122419}
24132420
2421+ void redis_get_restore_options (redisRestoreOptions * dst , HashTable * ht ) {
2422+ zend_string * key ;
2423+ zend_long lval ;
2424+ zval * zv ;
2425+
2426+ ZEND_ASSERT (dst != NULL );
2427+
2428+ memset (dst , 0 , sizeof (* dst ));
2429+ dst -> idletime = dst -> freq = -1 ;
2430+
2431+ if (ht == NULL )
2432+ return ;
2433+
2434+ ZEND_HASH_FOREACH_STR_KEY_VAL (ht , key , zv ) {
2435+ ZVAL_DEREF (zv );
2436+
2437+ if (key ) {
2438+ if (zend_string_equals_literal_ci (key , "IDLETIME" )) {
2439+ lval = zval_get_long (zv );
2440+ if (lval < 0 ) {
2441+ php_error_docref (NULL , E_WARNING , "IDLETIME must be >= 0" );
2442+ } else {
2443+ dst -> idletime = lval ;
2444+ dst -> freq = -1 ;
2445+ }
2446+ } else if (zend_string_equals_literal_ci (key , "FREQ" )) {
2447+ lval = zval_get_long (zv );
2448+ if (lval < 0 || lval > 255 ) {
2449+ php_error_docref (NULL , E_WARNING , "FREQ must be >= 0 and <= 255" );
2450+ } else {
2451+ dst -> freq = lval ;
2452+ dst -> idletime = -1 ;
2453+ }
2454+ } else {
2455+ php_error_docref (NULL , E_WARNING , "Unknown RESTORE option '%s'" , ZSTR_VAL (key ));
2456+ }
2457+ } else if (Z_TYPE_P (zv ) == IS_STRING ) {
2458+ if (zend_string_equals_literal_ci (Z_STR_P (zv ), "REPLACE" )) {
2459+ dst -> replace = 1 ;
2460+ } else if (zend_string_equals_literal_ci (Z_STR_P (zv ), "ABSTTL" )) {
2461+ dst -> absttl = 1 ;
2462+ } else {
2463+ php_error_docref (NULL , E_WARNING , "Unknown RESTORE option '%s'" , Z_STRVAL_P (zv ));
2464+ }
2465+ }
2466+ } ZEND_HASH_FOREACH_END ();
2467+ }
2468+
2469+ /* RESTORE */
2470+ int redis_restore_cmd (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
2471+ char * * cmd , int * cmd_len , short * slot , void * * ctx )
2472+ {
2473+ zend_string * key , * value = NULL ;
2474+ smart_string cmdstr = {0 };
2475+ HashTable * options = NULL ;
2476+ redisRestoreOptions opt ;
2477+ zend_long timeout = 0 ;
2478+ int argc ;
2479+
2480+ ZEND_PARSE_PARAMETERS_START (3 , 4 ) {
2481+ Z_PARAM_STR (key )
2482+ Z_PARAM_LONG (timeout )
2483+ Z_PARAM_STR (value )
2484+ Z_PARAM_OPTIONAL
2485+ Z_PARAM_ARRAY_HT_OR_NULL (options )
2486+ } ZEND_PARSE_PARAMETERS_END_EX (return FAILURE );
2487+
2488+ redis_get_restore_options (& opt , options );
2489+
2490+ argc = 3 + (opt .idletime > -1 ?2 :0 ) + (opt .freq > -1 ?2 :0 ) + !!opt .absttl + !!opt .replace ;
2491+ REDIS_CMD_INIT_SSTR_STATIC (& cmdstr , argc , "RESTORE" );
2492+
2493+ redis_cmd_append_sstr_key (& cmdstr , ZSTR_VAL (key ), ZSTR_LEN (key ), redis_sock , slot );
2494+ redis_cmd_append_sstr_long (& cmdstr , timeout );
2495+ redis_cmd_append_sstr_zstr (& cmdstr , value );
2496+
2497+ REDIS_CMD_APPEND_SSTR_OPT_STATIC (& cmdstr , opt .replace , "REPLACE" );
2498+ REDIS_CMD_APPEND_SSTR_OPT_STATIC (& cmdstr , opt .absttl , "ABSTTL" );
2499+
2500+ if (opt .idletime > -1 ) {
2501+ REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "IDLETIME" );
2502+ redis_cmd_append_sstr_long (& cmdstr , opt .idletime );
2503+ }
2504+
2505+ if (opt .freq > -1 ) {
2506+ REDIS_CMD_APPEND_SSTR_STATIC (& cmdstr , "FREQ" );
2507+ redis_cmd_append_sstr_long (& cmdstr , opt .freq );
2508+ }
2509+
2510+ * cmd = cmdstr .c ;
2511+ * cmd_len = cmdstr .len ;
2512+
2513+ return SUCCESS ;
2514+ }
24142515
24152516/* BITPOS */
24162517int redis_bitpos_cmd (INTERNAL_FUNCTION_PARAMETERS , RedisSock * redis_sock ,
0 commit comments