@@ -80,12 +80,35 @@ function readCodeFor(field, config, options, fieldNum) {
8080
8181function  compile ( fields ,  options ,  config )  { 
8282  const  parserFn  =  genFunc ( ) ; 
83-   let  i  =  0 ; 
8483  const  nullBitmapLength  =  Math . floor ( ( fields . length  +  7  +  2 )  /  8 ) ; 
8584
86-   /* eslint-disable no-trailing-spaces */ 
87-   /* eslint-disable no-spaced-func */ 
88-   /* eslint-disable no-unexpected-multiline */ 
85+   function  wrap ( field ,  packet )  { 
86+     return  { 
87+       type : typeNames [ field . columnType ] , 
88+       length : field . columnLength , 
89+       db : field . schema , 
90+       table : field . table , 
91+       name : field . name , 
92+       string : function  ( encoding  =  field . encoding )  { 
93+         if  ( field . columnType  ===  Types . JSON  &&  encoding  ===  field . encoding )  { 
94+           // Since for JSON columns mysql always returns charset 63 (BINARY), 
95+           // we have to handle it according to JSON specs and use "utf8", 
96+           // see https://github.com/sidorares/node-mysql2/issues/1661 
97+           console . warn ( 
98+             `typeCast: JSON column "${ field . name }  , 
99+           ) ; 
100+         } 
101+ 
102+         return  packet . readLengthCodedString ( encoding ) ; 
103+       } , 
104+       buffer : function  ( )  { 
105+         return  packet . readLengthCodedBuffer ( ) ; 
106+       } , 
107+       geometry : function  ( )  { 
108+         return  packet . parseGeometryValue ( ) ; 
109+       } , 
110+     } ; 
111+   } 
89112
90113  parserFn ( '(function(){' ) ; 
91114  parserFn ( 'return class BinaryRow {' ) ; 
@@ -96,24 +119,19 @@ function compile(fields, options, config) {
96119  if  ( options . rowsAsArray )  { 
97120    parserFn ( `const result = new Array(${ fields . length }  ) ; 
98121  }  else  { 
99-     parserFn ( " const result = {};" ) ; 
122+     parserFn ( ' const result = {};' ) ; 
100123  } 
101124
102-   const  resultTables  =  { } ; 
103-   let  resultTablesArray  =  [ ] ; 
104- 
105-   if  ( options . nestTables  ===  true )  { 
106-     for  ( i  =  0 ;  i  <  fields . length ;  i ++ )  { 
107-       resultTables [ fields [ i ] . table ]  =  1 ; 
108-     } 
109-     resultTablesArray  =  Object . keys ( resultTables ) ; 
110-     for  ( i  =  0 ;  i  <  resultTablesArray . length ;  i ++ )  { 
111-       parserFn ( `result[${ helpers . srcEscape ( resultTablesArray [ i ] ) }  ) ; 
112-     } 
125+   // Global typeCast 
126+   if  ( 
127+     typeof  config . typeCast  ===  'function'  && 
128+     typeof  options . typeCast  !==  'function' 
129+   )  { 
130+     options . typeCast  =  config . typeCast ; 
113131  } 
114132
115133  parserFn ( 'packet.readInt8();' ) ;  // status byte 
116-   for  ( i  =  0 ;  i  <  nullBitmapLength ;  ++ i )  { 
134+   for  ( let   i  =  0 ;  i  <  nullBitmapLength ;  ++ i )  { 
117135    parserFn ( `const nullBitmaskByte${ i }  ) ; 
118136  } 
119137
@@ -123,38 +141,44 @@ function compile(fields, options, config) {
123141  let  fieldName  =  '' ; 
124142  let  tableName  =  '' ; 
125143
126-   for  ( i  =  0 ;  i  <  fields . length ;  i ++ )  { 
144+   for  ( let   i  =  0 ;  i  <  fields . length ;  i ++ )  { 
127145    fieldName  =  helpers . srcEscape ( fields [ i ] . name ) ; 
128146    parserFn ( `// ${ fieldName } ${ typeNames [ fields [ i ] . columnType ] }  ) ; 
129147
130148    if  ( typeof  options . nestTables  ===  'string' )  { 
131-       tableName  =  helpers . srcEscape ( fields [ i ] . table ) ; 
132149      lvalue  =  `result[${ helpers . srcEscape (  
133-         fields [ i ] . table  +  options . nestTables  +  fields [ i ] . name  
150+         fields [ i ] . table  +  options . nestTables  +  fields [ i ] . name ,  
134151      ) }  ]`; 
135152    }  else  if  ( options . nestTables  ===  true )  { 
136153      tableName  =  helpers . srcEscape ( fields [ i ] . table ) ; 
154+       parserFn ( `if (!result[${ tableName } ${ tableName }  ) ; 
137155      lvalue  =  `result[${ tableName } ${ fieldName }  ; 
138156    }  else  if  ( options . rowsAsArray )  { 
139157      lvalue  =  `result[${ i . toString ( 10 ) }  ; 
140158    }  else  { 
141-       lvalue  =  `result[${ helpers . srcEscape ( fields [ i ] . name ) }  ; 
159+       lvalue  =  `result[${ fieldName }  ; 
160+     } 
161+ 
162+     if  ( options . typeCast  ===  false )  { 
163+       parserFn ( `${ lvalue }  ) ; 
164+     }  else  { 
165+       const  fieldWrapperVar  =  `fieldWrapper${ i }  ; 
166+       parserFn ( `const ${ fieldWrapperVar } ${ i }  ) ; 
167+       const  readCode  =  readCodeFor ( fields [ i ] ,  config ,  options ,  i ) ; 
168+ 
169+       parserFn ( `if (nullBitmaskByte${ nullByteIndex } ${ currentFieldNullBit }  ) ; 
170+       parserFn ( `${ lvalue }  ) ; 
171+       parserFn ( 'else {' ) ; 
172+       if  ( typeof  options . typeCast  ===  'function' )  { 
173+         parserFn ( 
174+           `${ lvalue } ${ fieldWrapperVar } ${ readCode }  , 
175+         ) ; 
176+       }  else  { 
177+         parserFn ( `${ lvalue } ${ readCode }  ) ; 
178+       } 
179+       parserFn ( '}' ) ; 
142180    } 
143181
144-     // TODO: this used to be an optimisation ( if column marked as NOT_NULL don't include code to check null 
145-     // bitmap at all, but it seems that we can't rely on this flag, see #178 
146-     // TODO: benchmark performance difference 
147-     // 
148-     // if (fields[i].flags & FieldFlags.NOT_NULL) { // don't need to check null bitmap if field can't be null. 
149-     //  result.push(lvalue + ' = ' + readCodeFor(fields[i], config)); 
150-     // } else if (fields[i].columnType == Types.NULL) { 
151-     //  result.push(lvalue + ' = null;'); 
152-     // } else { 
153-     parserFn ( `if (nullBitmaskByte${ nullByteIndex } ${ currentFieldNullBit }  ) ; 
154-     parserFn ( `${ lvalue }  ) ; 
155-     parserFn ( 'else' ) ; 
156-     parserFn ( `${ lvalue } ${ readCodeFor ( fields [ i ] ,  config ,  options ,  i ) }  ) ; 
157-     // } 
158182    currentFieldNullBit  *=  2 ; 
159183    if  ( currentFieldNullBit  ===  0x100 )  { 
160184      currentFieldNullBit  =  1 ; 
@@ -166,17 +190,13 @@ function compile(fields, options, config) {
166190  parserFn ( '}' ) ; 
167191  parserFn ( '};' ) ( '})()' ) ; 
168192
169-   /* eslint-enable no-trailing-spaces */ 
170-   /* eslint-enable no-spaced-func */ 
171-   /* eslint-enable no-unexpected-multiline */ 
172- 
173193  if  ( config . debug )  { 
174194    helpers . printDebugWithCode ( 
175195      'Compiled binary protocol row parser' , 
176-       parserFn . toString ( ) 
196+       parserFn . toString ( ) , 
177197    ) ; 
178198  } 
179-   return  parserFn . toFunction ( ) ; 
199+   return  parserFn . toFunction ( {  wrap  } ) ; 
180200} 
181201
182202function  getBinaryParser ( fields ,  options ,  config )  { 
0 commit comments