static_text_parser.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. 'use strict';
  2. const Types = require('../constants/types.js');
  3. const Charsets = require('../constants/charsets.js');
  4. const helpers = require('../helpers');
  5. const typeNames = [];
  6. for (const t in Types) {
  7. typeNames[Types[t]] = t;
  8. }
  9. function readField({ packet, type, charset, encoding, config, options }) {
  10. const supportBigNumbers = Boolean(
  11. options.supportBigNumbers || config.supportBigNumbers
  12. );
  13. const bigNumberStrings = Boolean(
  14. options.bigNumberStrings || config.bigNumberStrings
  15. );
  16. const timezone = options.timezone || config.timezone;
  17. const dateStrings = options.dateStrings || config.dateStrings;
  18. switch (type) {
  19. case Types.TINY:
  20. case Types.SHORT:
  21. case Types.LONG:
  22. case Types.INT24:
  23. case Types.YEAR:
  24. return packet.parseLengthCodedIntNoBigCheck();
  25. case Types.LONGLONG:
  26. if (supportBigNumbers && bigNumberStrings) {
  27. return packet.parseLengthCodedIntString();
  28. }
  29. return packet.parseLengthCodedInt(supportBigNumbers);
  30. case Types.FLOAT:
  31. case Types.DOUBLE:
  32. return packet.parseLengthCodedFloat();
  33. case Types.NULL:
  34. case Types.DECIMAL:
  35. case Types.NEWDECIMAL:
  36. if (config.decimalNumbers) {
  37. return packet.parseLengthCodedFloat();
  38. }
  39. return packet.readLengthCodedString('ascii');
  40. case Types.DATE:
  41. if (helpers.typeMatch(type, dateStrings, Types)) {
  42. return packet.readLengthCodedString('ascii');
  43. }
  44. return packet.parseDate(timezone);
  45. case Types.DATETIME:
  46. case Types.TIMESTAMP:
  47. if (helpers.typeMatch(type, dateStrings, Types)) {
  48. return packet.readLengthCodedString('ascii');
  49. }
  50. return packet.parseDateTime(timezone);
  51. case Types.TIME:
  52. return packet.readLengthCodedString('ascii');
  53. case Types.GEOMETRY:
  54. return packet.parseGeometryValue();
  55. case Types.VECTOR:
  56. return packet.parseVector();
  57. case Types.JSON:
  58. // Since for JSON columns mysql always returns charset 63 (BINARY),
  59. // we have to handle it according to JSON specs and use "utf8",
  60. // see https://github.com/sidorares/node-mysql2/issues/409
  61. return config.jsonStrings
  62. ? packet.readLengthCodedString('utf8')
  63. : JSON.parse(packet.readLengthCodedString('utf8'));
  64. default:
  65. if (charset === Charsets.BINARY) {
  66. return packet.readLengthCodedBuffer();
  67. }
  68. return packet.readLengthCodedString(encoding);
  69. }
  70. }
  71. function createTypecastField(field, packet) {
  72. return {
  73. type: typeNames[field.columnType],
  74. length: field.columnLength,
  75. db: field.schema,
  76. table: field.table,
  77. name: field.name,
  78. string: function (encoding = field.encoding) {
  79. if (field.columnType === Types.JSON && encoding === field.encoding) {
  80. // Since for JSON columns mysql always returns charset 63 (BINARY),
  81. // we have to handle it according to JSON specs and use "utf8",
  82. // see https://github.com/sidorares/node-mysql2/issues/1661
  83. console.warn(
  84. `typeCast: JSON column "${field.name}" is interpreted as BINARY by default, recommended to manually set utf8 encoding: \`field.string("utf8")\``
  85. );
  86. }
  87. return packet.readLengthCodedString(encoding);
  88. },
  89. buffer: function () {
  90. return packet.readLengthCodedBuffer();
  91. },
  92. geometry: function () {
  93. return packet.parseGeometryValue();
  94. },
  95. };
  96. }
  97. function getTextParser(_fields, _options, config) {
  98. return {
  99. next(packet, fields, options) {
  100. const result = options.rowsAsArray ? [] : {};
  101. for (let i = 0; i < fields.length; i++) {
  102. const field = fields[i];
  103. const typeCast = options.typeCast ? options.typeCast : config.typeCast;
  104. const next = () =>
  105. readField({
  106. packet,
  107. type: field.columnType,
  108. encoding: field.encoding,
  109. charset: field.characterSet,
  110. config,
  111. options,
  112. });
  113. let value;
  114. if (options.typeCast === false) {
  115. value = packet.readLengthCodedBuffer();
  116. } else if (typeof typeCast === 'function') {
  117. value = typeCast(createTypecastField(field, packet), next);
  118. } else {
  119. value = next();
  120. }
  121. if (options.rowsAsArray) {
  122. result.push(value);
  123. } else if (typeof options.nestTables === 'string') {
  124. result[
  125. `${helpers.fieldEscape(field.table, false)}${options.nestTables}${helpers.fieldEscape(field.name, false)}`
  126. ] = value;
  127. } else if (options.nestTables) {
  128. const tableName = helpers.fieldEscape(field.table, false);
  129. if (!result[tableName]) {
  130. result[tableName] = {};
  131. }
  132. result[tableName][helpers.fieldEscape(field.name, false)] = value;
  133. } else {
  134. result[helpers.fieldEscape(field.name, false)] = value;
  135. }
  136. }
  137. return result;
  138. },
  139. };
  140. }
  141. module.exports = getTextParser;