@@ -411,6 +411,10 @@ static const struct iproto_body_bin iproto_body_bin = {
411
411
0x81 , IPROTO_DATA , 0xdd , 0
412
412
};
413
413
414
+ static const struct iproto_body_bin iproto_body_bin_with_position = {
415
+ 0x82 , IPROTO_DATA , 0xdd , 0
416
+ };
417
+
414
418
/** Return a 4-byte numeric error code, with status flags. */
415
419
static inline uint32_t
416
420
iproto_encode_error (uint32_t error )
@@ -664,21 +668,56 @@ iproto_prepare_header(struct obuf *buf, struct obuf_svp *svp, size_t size)
664
668
return 0 ;
665
669
}
666
670
671
+ /** Reply select with IPROTO_DATA. */
667
672
void
668
673
iproto_reply_select (struct obuf * buf , struct obuf_svp * svp , uint64_t sync ,
669
674
uint32_t schema_version , uint32_t count )
670
675
{
671
676
char * pos = (char * ) obuf_svp_to_ptr (buf , svp );
672
677
iproto_header_encode (pos , IPROTO_OK , sync , schema_version ,
673
- obuf_size (buf ) - svp -> used -
674
- IPROTO_HEADER_LEN );
678
+ obuf_size (buf ) - svp -> used -
679
+ IPROTO_HEADER_LEN );
675
680
676
681
struct iproto_body_bin body = iproto_body_bin ;
677
682
body .v_data_len = mp_bswap_u32 (count );
678
683
679
684
memcpy (pos + IPROTO_HEADER_LEN , & body , sizeof (body ));
680
685
}
681
686
687
+ /** Reply select with IPROTO_DATA and IPROTO_POSITION. */
688
+ int
689
+ iproto_reply_select_with_position (struct obuf * buf , struct obuf_svp * svp ,
690
+ uint64_t sync , uint32_t schema_version ,
691
+ uint32_t count , const char * packed_pos ,
692
+ const char * packed_pos_end )
693
+ {
694
+ size_t packed_pos_size = packed_pos_end - packed_pos ;
695
+ size_t key_size = mp_sizeof_uint (IPROTO_POSITION );
696
+ size_t alloc_size = key_size + mp_sizeof_strl (packed_pos_size );
697
+ char * ptr = obuf_alloc (buf , alloc_size );
698
+ if (ptr == NULL ) {
699
+ diag_set (OutOfMemory , alloc_size , "obuf_alloc" , "ptr" );
700
+ return -1 ;
701
+ }
702
+ ptr = mp_encode_uint (ptr , IPROTO_POSITION );
703
+ mp_encode_strl (ptr , packed_pos_size );
704
+ if (obuf_dup (buf , packed_pos ,
705
+ packed_pos_size ) != packed_pos_size ) {
706
+ return -1 ;
707
+ }
708
+
709
+ char * pos = (char * )obuf_svp_to_ptr (buf , svp );
710
+ iproto_header_encode (pos , IPROTO_OK , sync , schema_version ,
711
+ obuf_size (buf ) - svp -> used -
712
+ IPROTO_HEADER_LEN );
713
+
714
+ struct iproto_body_bin body = iproto_body_bin_with_position ;
715
+ body .v_data_len = mp_bswap_u32 (count );
716
+
717
+ memcpy (pos + IPROTO_HEADER_LEN , & body , sizeof (body ));
718
+ return 0 ;
719
+ }
720
+
682
721
int
683
722
xrow_decode_sql (const struct xrow_header * row , struct sql_request * request )
684
723
{
@@ -850,6 +889,9 @@ xrow_decode_dml(struct xrow_header *row, struct request *request,
850
889
case IPROTO_ITERATOR :
851
890
request -> iterator = mp_decode_uint (& value );
852
891
break ;
892
+ case IPROTO_FETCH_POSITION :
893
+ request -> fetch_position = mp_decode_bool (& value );
894
+ break ;
853
895
case IPROTO_TUPLE :
854
896
request -> tuple = value ;
855
897
request -> tuple_end = data ;
@@ -874,6 +916,14 @@ xrow_decode_dml(struct xrow_header *row, struct request *request,
874
916
request -> new_tuple = value ;
875
917
request -> new_tuple_end = data ;
876
918
break ;
919
+ case IPROTO_AFTER_POSITION :
920
+ request -> after_position = value ;
921
+ request -> after_position_end = data ;
922
+ break ;
923
+ case IPROTO_AFTER_TUPLE :
924
+ request -> after_tuple = value ;
925
+ request -> after_tuple_end = data ;
926
+ break ;
877
927
default :
878
928
break ;
879
929
}
@@ -920,6 +970,17 @@ request_snprint(char *buf, int size, const struct request *request)
920
970
SNPRINT (total , snprintf , buf , size , ", new_tuple: " );
921
971
SNPRINT (total , mp_snprint , buf , size , request -> new_tuple );
922
972
}
973
+ if (request -> fetch_position ) {
974
+ SNPRINT (total , snprintf , buf , size , ", fetch_position: true" );
975
+ }
976
+ if (request -> after_position != NULL ) {
977
+ SNPRINT (total , snprintf , buf , size , ", after_position: " );
978
+ SNPRINT (total , mp_snprint , buf , size , request -> after_position );
979
+ }
980
+ if (request -> after_tuple != NULL ) {
981
+ SNPRINT (total , snprintf , buf , size , ", after_tuple: " );
982
+ SNPRINT (total , mp_snprint , buf , size , request -> after_tuple );
983
+ }
923
984
SNPRINT (total , snprintf , buf , size , "}" );
924
985
return total ;
925
986
}
937
998
xrow_encode_dml (const struct request * request , struct region * region ,
938
999
struct iovec * iov )
939
1000
{
1001
+ assert (request != NULL );
1002
+ /* Select is unexpected here. Hence, pagination option too. */
1003
+ assert (request -> header == NULL ||
1004
+ request -> header -> type != IPROTO_SELECT );
1005
+ assert (request -> after_position == NULL );
1006
+ assert (request -> after_tuple == NULL );
1007
+ assert (!request -> fetch_position );
940
1008
int iovcnt = 1 ;
941
1009
const int MAP_LEN_MAX = 40 ;
942
1010
uint32_t key_len = request -> key_end - request -> key ;
0 commit comments