123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- // Dependencies
- var _ = require('@sailshq/lodash');
- module.exports = {
- friendlyName: 'Parse native query error',
- description: 'Attempt to identify and parse a raw error from sending a native query and normalize it to a standard error footprint.',
- moreInfoUrl: 'https://github.com/node-machine/waterline-driver-interface#footprints',
- sideEffects: 'cacheable',
- sync: true,
- inputs: {
- nativeQueryError: {
- description: 'The error sent back from the database as a result of a failed native query.',
- extendedDescription: 'This is referring to the raw error; i.e. the `error` property of the dictionary returned through the `queryFailed` exit of `sendNativeQuery()` in this driver.',
- required: true,
- example: '==='
- },
- meta: {
- friendlyName: 'Meta (custom)',
- description: 'Additional stuff to pass to the driver.',
- extendedDescription: 'This is reserved for custom driver-specific extensions. Please refer to the documentation for the driver you are using for more specific information.',
- example: '==='
- }
- },
- exits: {
- success: {
- description: 'The normalization is complete. If the error cannot be normalized into any other more specific footprint, then the catchall footprint will be returned.',
- moreInfoUrl: 'https://github.com/node-machine/waterline-driver-interface#footprints',
- outputVariableName: 'report',
- outputDescription: 'The `footprint` property is the normalized "footprint" representing the provided raw error. Conforms to one of a handful of standardized footprint types expected by the Waterline driver interface. The `meta` property is reserved for custom driver-specific extensions.',
- outputExample: '==='
- // example: {
- // footprint: {},
- // meta: '==='
- // }
- },
- },
- fn: function parseNativeQueryError(inputs, exits) {
- // Quick reference of hand-tested errors:
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_PARSE_ERROR'
- // `errno` : 1064
- // `sqlState` : '42000'
- // `index` : 0
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_NO_SUCH_TABLE'
- // `errno` : 1146
- // `sqlState` : '42S02'
- // `index` : 0
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_DUP_ENTRY'
- // `errno` : 1062
- // `sqlState` : '23000'
- // `index` : 0
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // Local variable (`err`) for convenience.
- var err = inputs.nativeQueryError;
- // `footprint` is primarily what will be returned by this machine.
- // For miscellaneous errors which are not explicitly in the
- // spec, return the catchall footprint. Drivers should not
- // add their own additional footprints-- instead, if they want
- // to allow for easily identifying a particular error, the
- // `catchall` footprint should still be used; but additional
- // information sent back in `meta`.
- var footprint = { identity: 'catchall' };
- // If the incoming native query error is not an object, or it is
- // missing a `code` property, then we'll go ahead and bail out w/
- // the "catchall" footprint to avoid continually doing these basic
- // checks in the more detailed error negotiation below.
- if (!_.isObject(err) || !err.code) {
- return exits.success({
- footprint: footprint,
- meta: inputs.meta
- });
- }
- //
- // Otherwise, continue inspecting the native query error in more detail.
- //
- // > Note that the conditional blocks below are **disjoint**--
- // > that is, only one of them should be run.
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_DUP_ENTRY'
- // `errno` : 1062
- // `sqlState` : '23000'
- // `index` : 0
- //
- // -- Recognized as the `notUnique` footprint from the
- // Waterline driver spec. If additional information
- // is needed in userland beyond what is guaranteed in
- // the spec, then you should take advantage of `meta`.
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- if (err.code === 'ER_DUP_ENTRY') {
- // Negotiate `notUnique` error footprint.
- footprint = {
- identity: 'notUnique',
- keys: []
- };
- // Now build our footprint's `keys` property by manually parsing
- // the MySQL error message and extracting the relevant bits.
- // (See also: https://github.com/balderdashy/sails-mysql/blob/2c414f1191c3595df2cea8e40259811eb3ca05f9/lib/adapter.js#L1223)
- if (_.isString(err.message)) {
- var matches = err.message.match(/Duplicate entry '.*' for key '(.*?)'$/);
- if (matches && matches.length > 0) {
- footprint.keys.push(matches[1]);
- }
- }
- }
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_NO_SUCH_TABLE'
- // `errno` : 1146
- // `sqlState` : '42S02'
- // `index` : 0
- //
- // -- Not in specification yet; just listed here for
- // reference. If this driver wants to move ahead of
- // the core Waterline/machine spec, this can be handled
- // using the `catchall` footprint + `meta`.
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // else if ( ... ){
- // footprint = { identity: 'catchall' };
- // // e.g.
- // meta = { problem: 'noSuchTable', foo: ..., bar: ... };
- // }
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // `code` : 'ER_PARSE_ERROR'
- // `errno` : 1064
- // `sqlState` : '42000'
- // `index` : 0
- //
- // -- Not in specification yet; just listed here for
- // reference. If this driver wants to move ahead of
- // the core Waterline/machine spec, this can be handled
- // using the `catchall` footprint + `meta`.
- // --o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o--o-<>
- // else if ( ... ){
- // footprint = { identity: 'catchall' };
- // // e.g.
- // meta = { problem: 'couldNotParse', foo: ..., bar: ... };
- // }
- // Finally, return the normalized footprint.
- //
- // (as well as any additional metadata that was stuffed
- // into `meta` above)
- return exits.success({
- footprint: footprint,
- meta: inputs.meta
- });
- }
- };
|