@@ -56,6 +56,17 @@ NativeQuery.prototype.handleError = function (err) {
5656 err [ normalizedFieldName ] = fields [ key ]
5757 }
5858 }
59+
60+ // For maxResultSize exceeded errors, make sure we emit the error to the client too
61+ if ( err . code === 'RESULT_SIZE_EXCEEDED' ) {
62+ if ( this . native && this . native . connection ) {
63+ // Need to emit the error on the client/connection level too
64+ process . nextTick ( ( ) => {
65+ this . native . connection . emit ( 'error' , err )
66+ } )
67+ }
68+ }
69+
5970 if ( this . callback ) {
6071 this . callback ( err )
6172 } else {
@@ -89,6 +100,9 @@ NativeQuery.prototype.submit = function (client) {
89100 this . native = client . native
90101 client . native . arrayMode = this . _arrayMode
91102
103+ // Get the maxResultSize from the client if it's set
104+ this . _maxResultSize = client . _maxResultSize
105+
92106 var after = function ( err , rows , results ) {
93107 client . native . arrayMode = false
94108 setImmediate ( function ( ) {
@@ -100,6 +114,30 @@ NativeQuery.prototype.submit = function (client) {
100114 return self . handleError ( err )
101115 }
102116
117+ // Check the result size if maxResultSize is configured
118+ if ( self . _maxResultSize ) {
119+ // Calculate result size (rough approximation)
120+ let resultSize = 0
121+
122+ // For multiple result sets
123+ if ( results . length > 1 ) {
124+ for ( let i = 0 ; i < rows . length ; i ++ ) {
125+ resultSize += self . _calculateResultSize ( rows [ i ] )
126+ }
127+ } else if ( rows . length > 0 ) {
128+ resultSize = self . _calculateResultSize ( rows )
129+ }
130+
131+ // If the size limit is exceeded, generate an error
132+ if ( resultSize > self . _maxResultSize ) {
133+ const error = new Error ( 'Query result size exceeded the configured limit' )
134+ error . code = 'RESULT_SIZE_EXCEEDED'
135+ error . resultSize = resultSize
136+ error . maxResultSize = self . _maxResultSize
137+ return self . handleError ( error )
138+ }
139+ }
140+
103141 // emit row events for each row in the result
104142 if ( self . _emitRowEvents ) {
105143 if ( results . length > 1 ) {
@@ -166,3 +204,59 @@ NativeQuery.prototype.submit = function (client) {
166204 client . native . query ( this . text , after )
167205 }
168206}
207+
208+ // Helper method to estimate the size of a result set
209+ NativeQuery . prototype . _calculateResultSize = function ( rows ) {
210+ let size = 0
211+
212+ // For empty results, return 0
213+ if ( ! rows || rows . length === 0 ) {
214+ return 0
215+ }
216+
217+ // For array mode, calculate differently
218+ if ( this . _arrayMode ) {
219+ // Just use a rough approximation based on number of rows
220+ return rows . length * 100
221+ }
222+
223+ // For each row, approximate its size
224+ for ( let i = 0 ; i < rows . length ; i ++ ) {
225+ const row = rows [ i ]
226+
227+ // Add base row size
228+ size += 24 // Overhead per row
229+
230+ // Add size of each column
231+ for ( const key in row ) {
232+ if ( Object . prototype . hasOwnProperty . call ( row , key ) ) {
233+ const value = row [ key ]
234+
235+ // Add key size
236+ size += key . length * 2 // Assume 2 bytes per character
237+
238+ // Add value size based on type
239+ if ( value === null || value === undefined ) {
240+ size += 8
241+ } else if ( typeof value === 'string' ) {
242+ size += value . length * 2 // Assume 2 bytes per character
243+ } else if ( typeof value === 'number' ) {
244+ size += 8
245+ } else if ( typeof value === 'boolean' ) {
246+ size += 4
247+ } else if ( value instanceof Date ) {
248+ size += 8
249+ } else if ( Buffer . isBuffer ( value ) ) {
250+ size += value . length
251+ } else if ( Array . isArray ( value ) ) {
252+ size += 16 + value . length * 8
253+ } else {
254+ // For objects, use a rough estimate
255+ size += 32 + JSON . stringify ( value ) . length * 2
256+ }
257+ }
258+ }
259+ }
260+
261+ return size
262+ }
0 commit comments