1313// limitations under the License.
1414
1515use std:: collections:: { BTreeMap , HashMap } ;
16+ use std:: fmt:: { Display , Formatter } ;
1617use std:: str:: FromStr ;
1718use std:: sync:: Arc ;
1819
1920use arrow:: datatypes:: DataType as ArrowDataType ;
20- use arrow_schema:: Fields ;
2121use common_base:: bytes:: Bytes ;
2222use serde:: { Deserialize , Serialize } ;
2323use snafu:: ResultExt ;
@@ -68,7 +68,7 @@ impl JsonType {
6868 /// - if not, the json is one of bool, number, string or array, make it a special field called
6969 /// [JSON_PLAIN_FIELD_NAME] with metadata [JSON_PLAIN_FIELD_METADATA_KEY] = `"true"` in a
7070 /// struct with only that field.
71- pub ( crate ) fn as_struct_type ( & self ) -> StructType {
71+ pub fn as_struct_type ( & self ) -> StructType {
7272 match & self . format {
7373 JsonFormat :: Jsonb => StructType :: default ( ) ,
7474 JsonFormat :: Native ( inner) => match inner. as_ref ( ) {
@@ -98,7 +98,7 @@ impl JsonType {
9898 }
9999
100100 /// Try to merge this json type with others, error on datatype conflict.
101- pub ( crate ) fn merge ( & mut self , other : & JsonType ) -> Result < ( ) > {
101+ pub fn merge ( & mut self , other : & JsonType ) -> Result < ( ) > {
102102 match ( & self . format , & other. format ) {
103103 ( JsonFormat :: Jsonb , JsonFormat :: Jsonb ) => Ok ( ( ) ) ,
104104 ( JsonFormat :: Native ( this) , JsonFormat :: Native ( that) ) => {
@@ -113,7 +113,8 @@ impl JsonType {
113113 }
114114 }
115115
116- pub ( crate ) fn is_mergeable ( & self , other : & JsonType ) -> bool {
116+ /// Check if it can merge with `other` json type.
117+ pub fn is_mergeable ( & self , other : & JsonType ) -> bool {
117118 match ( & self . format , & other. format ) {
118119 ( JsonFormat :: Jsonb , JsonFormat :: Jsonb ) => true ,
119120 ( JsonFormat :: Native ( this) , JsonFormat :: Native ( that) ) => {
@@ -122,6 +123,49 @@ impl JsonType {
122123 _ => false ,
123124 }
124125 }
126+
127+ /// Check if it includes all fields in `other` json type.
128+ pub fn is_include ( & self , other : & JsonType ) -> bool {
129+ match ( & self . format , & other. format ) {
130+ ( JsonFormat :: Jsonb , JsonFormat :: Jsonb ) => true ,
131+ ( JsonFormat :: Native ( this) , JsonFormat :: Native ( that) ) => {
132+ is_include ( this. as_ref ( ) , that. as_ref ( ) )
133+ }
134+ _ => false ,
135+ }
136+ }
137+ }
138+
139+ fn is_include ( this : & ConcreteDataType , that : & ConcreteDataType ) -> bool {
140+ fn is_include_struct ( this : & StructType , that : & StructType ) -> bool {
141+ let this_fields = this. fields ( ) ;
142+ let this_fields = this_fields
143+ . iter ( )
144+ . map ( |x| ( x. name ( ) , x) )
145+ . collect :: < HashMap < _ , _ > > ( ) ;
146+
147+ for that_field in that. fields ( ) . iter ( ) {
148+ let Some ( this_field) = this_fields. get ( that_field. name ( ) ) else {
149+ return false ;
150+ } ;
151+ if !is_include ( this_field. data_type ( ) , that_field. data_type ( ) ) {
152+ return false ;
153+ }
154+ }
155+ true
156+ }
157+
158+ match ( this, that) {
159+ ( this, that) if this == that => true ,
160+ ( ConcreteDataType :: List ( this) , ConcreteDataType :: List ( that) ) => {
161+ is_include ( this. item_type ( ) , that. item_type ( ) )
162+ }
163+ ( ConcreteDataType :: Struct ( this) , ConcreteDataType :: Struct ( that) ) => {
164+ is_include_struct ( this, that)
165+ }
166+ ( _, ConcreteDataType :: Null ( _) ) => true ,
167+ _ => false ,
168+ }
125169}
126170
127171fn is_mergeable ( this : & ConcreteDataType , that : & ConcreteDataType ) -> bool {
@@ -223,7 +267,7 @@ impl DataType for JsonType {
223267 fn as_arrow_type ( & self ) -> ArrowDataType {
224268 match self . format {
225269 JsonFormat :: Jsonb => ArrowDataType :: Binary ,
226- JsonFormat :: Native ( _) => ArrowDataType :: Struct ( Fields :: empty ( ) ) ,
270+ JsonFormat :: Native ( _) => self . as_struct_type ( ) . as_arrow_type ( ) ,
227271 }
228272 }
229273
@@ -242,6 +286,12 @@ impl DataType for JsonType {
242286 }
243287}
244288
289+ impl Display for JsonType {
290+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
291+ write ! ( f, "{}" , self . name( ) )
292+ }
293+ }
294+
245295/// Converts a json type value to string
246296pub fn jsonb_to_string ( val : & [ u8 ] ) -> Result < String > {
247297 match jsonb:: from_slice ( val) {
0 commit comments