12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ use std:: ops:: Deref ;
15
16
use std:: sync:: atomic:: AtomicBool ;
16
17
use std:: sync:: atomic:: Ordering ;
17
18
use std:: sync:: Arc ;
19
+ use std:: sync:: LazyLock ;
18
20
19
21
use arrow_flight:: FlightData ;
20
22
use arrow_flight:: SchemaAsIpc ;
21
23
use arrow_ipc:: writer;
22
24
use arrow_ipc:: writer:: IpcWriteOptions ;
25
+ use arrow_ipc:: MessageBuilder ;
26
+ use arrow_ipc:: MessageHeader ;
27
+ use arrow_ipc:: MetadataVersion ;
23
28
use arrow_schema:: Schema as ArrowSchema ;
29
+ use bytes:: Bytes ;
24
30
use databend_common_base:: base:: tokio;
25
31
use databend_common_exception:: ErrorCode ;
26
32
use databend_common_exception:: Result ;
@@ -33,6 +39,7 @@ use databend_common_sql::Planner;
33
39
use databend_common_storages_fuse:: TableContext ;
34
40
use futures:: Stream ;
35
41
use futures:: StreamExt ;
42
+ use prost:: bytes;
36
43
use serde:: Deserialize ;
37
44
use serde:: Serialize ;
38
45
use tonic:: Status ;
@@ -47,6 +54,29 @@ use crate::sessions::Session;
47
54
/// A app_metakey which indicates the data is a progress type
48
55
static H_PROGRESS : u8 = 0x01 ;
49
56
57
+ /// The generated app metadata for our progress.
58
+ static APP_METADATA_PROGRESS : LazyLock < Bytes > = LazyLock :: new ( || Bytes :: from ( vec ! [ H_PROGRESS ] ) ) ;
59
+
60
+ /// The data header for our progress.
61
+ ///
62
+ /// This build process is inspired from [arrow_ipc::writer::IpcDataGenerator](https://docs.rs/arrow-ipc/51.0.0/arrow_ipc/writer/struct.IpcDataGenerator.html#method.schema_to_bytes)
63
+ static DATA_HEADER_PROGRESS : LazyLock < Bytes > = LazyLock :: new ( || {
64
+ let mut fbb = flatbuffers:: FlatBufferBuilder :: new ( ) ;
65
+
66
+ let mut builder = MessageBuilder :: new ( & mut fbb) ;
67
+ // Use the same version with arrow_ipc.
68
+ builder. add_version ( MetadataVersion :: V5 ) ;
69
+ // Use NONE as the header type.
70
+ builder. add_header_type ( MessageHeader :: NONE ) ;
71
+ // We don't have other data to write in this message, just finish.
72
+ let data = builder. finish ( ) ;
73
+
74
+ // finish the flat buffers.
75
+ fbb. finish ( data, None ) ;
76
+
77
+ Bytes :: copy_from_slice ( fbb. finished_data ( ) )
78
+ } ) ;
79
+
50
80
impl FlightSqlServiceImpl {
51
81
pub ( crate ) fn schema_to_flight_data ( data_schema : DataSchema ) -> FlightData {
52
82
let arrow_schema = ArrowSchema :: from ( & data_schema) ;
@@ -69,6 +99,16 @@ impl FlightSqlServiceImpl {
69
99
Ok ( encoded_batch. into ( ) )
70
100
}
71
101
102
+ fn progress_to_flight_data ( progress : & ProgressValue ) -> Result < FlightData > {
103
+ let progress = serde_json:: to_vec ( & progress)
104
+ . map_err ( |e| ErrorCode :: Internal ( format ! ( "encode progress into json failed: {e:?}" ) ) ) ?;
105
+
106
+ Ok ( FlightData :: new ( )
107
+ . with_app_metadata ( APP_METADATA_PROGRESS . deref ( ) . clone ( ) )
108
+ . with_data_header ( DATA_HEADER_PROGRESS . deref ( ) . clone ( ) )
109
+ . with_data_body ( Bytes :: from ( progress) ) )
110
+ }
111
+
72
112
#[ async_backtrace:: framed]
73
113
pub async fn plan_sql (
74
114
& self ,
@@ -211,12 +251,7 @@ impl FlightSqlServiceImpl {
211
251
progress. write_bytes = write_progress. bytes ;
212
252
}
213
253
214
- let progress = serde_json:: to_vec ( & progress) . unwrap ( ) ;
215
- Some ( FlightData {
216
- app_metadata : vec ! [ H_PROGRESS ] . into ( ) ,
217
- data_body : progress. into ( ) ,
218
- ..Default :: default ( )
219
- } )
254
+ Some ( Self :: progress_to_flight_data ( & progress) . unwrap ( ) )
220
255
} ;
221
256
222
257
while !is_finished. load ( Ordering :: SeqCst ) {
0 commit comments