153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			153 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | 
 | ||
|  | const Types = require('../constants/types.js'); | ||
|  | const Charsets = require('../constants/charsets.js'); | ||
|  | const helpers = require('../helpers'); | ||
|  | 
 | ||
|  | const typeNames = []; | ||
|  | for (const t in Types) { | ||
|  |   typeNames[Types[t]] = t; | ||
|  | } | ||
|  | 
 | ||
|  | function readField({ packet, type, charset, encoding, config, options }) { | ||
|  |   const supportBigNumbers = Boolean( | ||
|  |     options.supportBigNumbers || config.supportBigNumbers | ||
|  |   ); | ||
|  |   const bigNumberStrings = Boolean( | ||
|  |     options.bigNumberStrings || config.bigNumberStrings | ||
|  |   ); | ||
|  |   const timezone = options.timezone || config.timezone; | ||
|  |   const dateStrings = options.dateStrings || config.dateStrings; | ||
|  | 
 | ||
|  |   switch (type) { | ||
|  |     case Types.TINY: | ||
|  |     case Types.SHORT: | ||
|  |     case Types.LONG: | ||
|  |     case Types.INT24: | ||
|  |     case Types.YEAR: | ||
|  |       return packet.parseLengthCodedIntNoBigCheck(); | ||
|  |     case Types.LONGLONG: | ||
|  |       if (supportBigNumbers && bigNumberStrings) { | ||
|  |         return packet.parseLengthCodedIntString(); | ||
|  |       } | ||
|  |       return packet.parseLengthCodedInt(supportBigNumbers); | ||
|  |     case Types.FLOAT: | ||
|  |     case Types.DOUBLE: | ||
|  |       return packet.parseLengthCodedFloat(); | ||
|  |     case Types.NULL: | ||
|  |     case Types.DECIMAL: | ||
|  |     case Types.NEWDECIMAL: | ||
|  |       if (config.decimalNumbers) { | ||
|  |         return packet.parseLengthCodedFloat(); | ||
|  |       } | ||
|  |       return packet.readLengthCodedString('ascii'); | ||
|  |     case Types.DATE: | ||
|  |       if (helpers.typeMatch(type, dateStrings, Types)) { | ||
|  |         return packet.readLengthCodedString('ascii'); | ||
|  |       } | ||
|  |       return packet.parseDate(timezone); | ||
|  |     case Types.DATETIME: | ||
|  |     case Types.TIMESTAMP: | ||
|  |       if (helpers.typeMatch(type, dateStrings, Types)) { | ||
|  |         return packet.readLengthCodedString('ascii'); | ||
|  |       } | ||
|  |       return packet.parseDateTime(timezone); | ||
|  |     case Types.TIME: | ||
|  |       return packet.readLengthCodedString('ascii'); | ||
|  |     case Types.GEOMETRY: | ||
|  |       return packet.parseGeometryValue(); | ||
|  |     case Types.VECTOR: | ||
|  |       return packet.parseVector(); | ||
|  |     case Types.JSON: | ||
|  |       // Since for JSON columns mysql always returns charset 63 (BINARY),
 | ||
|  |       // we have to handle it according to JSON specs and use "utf8",
 | ||
|  |       // see https://github.com/sidorares/node-mysql2/issues/409
 | ||
|  |       return config.jsonStrings | ||
|  |         ? packet.readLengthCodedString('utf8') | ||
|  |         : JSON.parse(packet.readLengthCodedString('utf8')); | ||
|  |     default: | ||
|  |       if (charset === Charsets.BINARY) { | ||
|  |         return packet.readLengthCodedBuffer(); | ||
|  |       } | ||
|  |       return packet.readLengthCodedString(encoding); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function createTypecastField(field, packet) { | ||
|  |   return { | ||
|  |     type: typeNames[field.columnType], | ||
|  |     length: field.columnLength, | ||
|  |     db: field.schema, | ||
|  |     table: field.table, | ||
|  |     name: field.name, | ||
|  |     string: function (encoding = field.encoding) { | ||
|  |       if (field.columnType === Types.JSON && encoding === field.encoding) { | ||
|  |         // Since for JSON columns mysql always returns charset 63 (BINARY),
 | ||
|  |         // we have to handle it according to JSON specs and use "utf8",
 | ||
|  |         // see https://github.com/sidorares/node-mysql2/issues/1661
 | ||
|  |         console.warn( | ||
|  |           `typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\`` | ||
|  |         ); | ||
|  |       } | ||
|  |       return packet.readLengthCodedString(encoding); | ||
|  |     }, | ||
|  |     buffer: function () { | ||
|  |       return packet.readLengthCodedBuffer(); | ||
|  |     }, | ||
|  |     geometry: function () { | ||
|  |       return packet.parseGeometryValue(); | ||
|  |     }, | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | function getTextParser(_fields, _options, config) { | ||
|  |   return { | ||
|  |     next(packet, fields, options) { | ||
|  |       const result = options.rowsAsArray ? [] : {}; | ||
|  |       for (let i = 0; i < fields.length; i++) { | ||
|  |         const field = fields[i]; | ||
|  |         const typeCast = options.typeCast ? options.typeCast : config.typeCast; | ||
|  |         const next = () => | ||
|  |           readField({ | ||
|  |             packet, | ||
|  |             type: field.columnType, | ||
|  |             encoding: field.encoding, | ||
|  |             charset: field.characterSet, | ||
|  |             config, | ||
|  |             options, | ||
|  |           }); | ||
|  | 
 | ||
|  |         let value; | ||
|  | 
 | ||
|  |         if (options.typeCast === false) { | ||
|  |           value = packet.readLengthCodedBuffer(); | ||
|  |         } else if (typeof typeCast === 'function') { | ||
|  |           value = typeCast(createTypecastField(field, packet), next); | ||
|  |         } else { | ||
|  |           value = next(); | ||
|  |         } | ||
|  | 
 | ||
|  |         if (options.rowsAsArray) { | ||
|  |           result.push(value); | ||
|  |         } else if (typeof options.nestTables === 'string') { | ||
|  |           result[ | ||
|  |             `${helpers.fieldEscape(field.table, false)}${options.nestTables}${helpers.fieldEscape(field.name, false)}` | ||
|  |           ] = value; | ||
|  |         } else if (options.nestTables) { | ||
|  |           const tableName = helpers.fieldEscape(field.table, false); | ||
|  |           if (!result[tableName]) { | ||
|  |             result[tableName] = {}; | ||
|  |           } | ||
|  |           result[tableName][helpers.fieldEscape(field.name, false)] = value; | ||
|  |         } else { | ||
|  |           result[helpers.fieldEscape(field.name, false)] = value; | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       return result; | ||
|  |     }, | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = getTextParser; |