Skip to content

Commit 5ed5163

Browse files
committed
feat: add 32767 byte line length limit to DBMS_OUTPUT
Oracle enforces a maximum line length of 32767 bytes per line. Exceeding this limit raises ORU-10028 error. - Check line length in PUT_LINE before adding to buffer - Check accumulated line length in PUT before appending - Add test cases for line length boundary conditions Verified against Oracle 23.26 Free. Fixes #21
1 parent cf94373 commit 5ed5163

File tree

3 files changed

+118
-3
lines changed

3 files changed

+118
-3
lines changed

contrib/ivorysql_ora/expected/ora_dbms_output.out

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,48 @@ NOTICE: [Iteration 1]
523523
NOTICE: [Iteration 2]
524524
NOTICE: [Iteration 3]
525525
-- =============================================================================
526+
-- Section 9: Line Length Limit (32767 bytes)
527+
-- =============================================================================
528+
-- Test 9.1: PUT_LINE at exactly 32767 bytes (should succeed)
529+
DECLARE
530+
long_line TEXT := repeat('X', 32767);
531+
line TEXT;
532+
status INTEGER;
533+
BEGIN
534+
dbms_output.enable(100000);
535+
dbms_output.put_line(long_line);
536+
dbms_output.get_line(line, status);
537+
RAISE NOTICE 'Test 9.1 - Max line (32767 bytes): length=%, Status=%', length(line), status;
538+
END;
539+
/
540+
NOTICE: Test 9.1 - Max line (32767 bytes): length=32767, Status=0
541+
-- Test 9.2: PUT_LINE exceeding 32767 bytes (should fail with ORU-10028)
542+
DECLARE
543+
long_line TEXT := repeat('X', 32768);
544+
BEGIN
545+
dbms_output.enable(100000);
546+
dbms_output.put_line(long_line);
547+
RAISE NOTICE 'Test 9.2 - Should not reach here';
548+
EXCEPTION WHEN OTHERS THEN
549+
RAISE NOTICE 'Test 9.2 - Line overflow error: %', SQLERRM;
550+
END;
551+
/
552+
NOTICE: Test 9.2 - Line overflow error: ORU-10028: line length overflow, limit of 32767 bytes per line
553+
-- Test 9.3: PUT accumulating to exceed 32767 bytes (should fail with ORU-10028)
554+
DECLARE
555+
chunk TEXT := repeat('X', 32767);
556+
BEGIN
557+
dbms_output.enable(100000);
558+
dbms_output.put(chunk);
559+
dbms_output.put('Y'); -- This triggers the overflow
560+
dbms_output.new_line();
561+
RAISE NOTICE 'Test 9.3 - Should not reach here';
562+
EXCEPTION WHEN OTHERS THEN
563+
RAISE NOTICE 'Test 9.3 - PUT overflow error: %', SQLERRM;
564+
END;
565+
/
566+
NOTICE: Test 9.3 - PUT overflow error: ORU-10028: line length overflow, limit of 32767 bytes per line
567+
-- =============================================================================
526568
-- Cleanup
527569
-- =============================================================================
528570
DROP PROCEDURE test_output_proc;

contrib/ivorysql_ora/sql/ora_dbms_output.sql

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,48 @@ BEGIN
500500
END;
501501
/
502502

503+
-- =============================================================================
504+
-- Section 9: Line Length Limit (32767 bytes)
505+
-- =============================================================================
506+
-- Test 9.1: PUT_LINE at exactly 32767 bytes (should succeed)
507+
DECLARE
508+
long_line TEXT := repeat('X', 32767);
509+
line TEXT;
510+
status INTEGER;
511+
BEGIN
512+
dbms_output.enable(100000);
513+
dbms_output.put_line(long_line);
514+
dbms_output.get_line(line, status);
515+
RAISE NOTICE 'Test 9.1 - Max line (32767 bytes): length=%, Status=%', length(line), status;
516+
END;
517+
/
518+
519+
-- Test 9.2: PUT_LINE exceeding 32767 bytes (should fail with ORU-10028)
520+
DECLARE
521+
long_line TEXT := repeat('X', 32768);
522+
BEGIN
523+
dbms_output.enable(100000);
524+
dbms_output.put_line(long_line);
525+
RAISE NOTICE 'Test 9.2 - Should not reach here';
526+
EXCEPTION WHEN OTHERS THEN
527+
RAISE NOTICE 'Test 9.2 - Line overflow error: %', SQLERRM;
528+
END;
529+
/
530+
531+
-- Test 9.3: PUT accumulating to exceed 32767 bytes (should fail with ORU-10028)
532+
DECLARE
533+
chunk TEXT := repeat('X', 32767);
534+
BEGIN
535+
dbms_output.enable(100000);
536+
dbms_output.put(chunk);
537+
dbms_output.put('Y'); -- This triggers the overflow
538+
dbms_output.new_line();
539+
RAISE NOTICE 'Test 9.3 - Should not reach here';
540+
EXCEPTION WHEN OTHERS THEN
541+
RAISE NOTICE 'Test 9.3 - PUT overflow error: %', SQLERRM;
542+
END;
543+
/
544+
503545
-- =============================================================================
504546
-- Cleanup
505547
-- =============================================================================

contrib/ivorysql_ora/src/builtin_packages/dbms_output/dbms_output.c

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ typedef struct DbmsOutputBuffer
5959
/* Global buffer - one per backend process */
6060
static DbmsOutputBuffer *output_buffer = NULL;
6161

62+
/* Oracle line length limit: 32767 bytes per line */
63+
#define DBMS_OUTPUT_MAX_LINE_LENGTH 32767
64+
6265
/* Internal function declarations */
6366
static void init_output_buffer(int buffer_size);
6467
static void cleanup_output_buffer(void);
@@ -311,12 +314,14 @@ ora_dbms_output_disable(PG_FUNCTION_ARGS)
311314
* Output a line to the buffer (with newline).
312315
* If there's pending PUT text, append it first (Oracle behavior).
313316
* Oracle behavior: NULL stores actual NULL in buffer (not empty string).
317+
* Oracle behavior: raises ORU-10028 if line exceeds 32767 bytes.
314318
*/
315319
Datum
316320
ora_dbms_output_put_line(PG_FUNCTION_ARGS)
317321
{
318322
char *line_str;
319323
bool is_null = false;
324+
int line_len = 0;
320325

321326
/* Silently discard if buffer not enabled (Oracle behavior) */
322327
if (output_buffer == NULL || !output_buffer->enabled)
@@ -332,11 +337,19 @@ ora_dbms_output_put_line(PG_FUNCTION_ARGS)
332337
{
333338
text *line_text = PG_GETARG_TEXT_PP(0);
334339
line_str = text_to_cstring(line_text);
340+
line_len = strlen(line_str);
335341
}
336342

337343
/* If there's pending PUT text, append it first (Oracle behavior) */
338344
if (output_buffer->current_line->len > 0)
339345
{
346+
/* Check line length limit BEFORE appending (Oracle behavior) */
347+
if (output_buffer->current_line->len + line_len > DBMS_OUTPUT_MAX_LINE_LENGTH)
348+
ereport(ERROR,
349+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
350+
errmsg("ORU-10028: line length overflow, limit of %d bytes per line",
351+
DBMS_OUTPUT_MAX_LINE_LENGTH)));
352+
340353
/* Append non-NULL text to current line */
341354
if (!is_null)
342355
appendStringInfoString(output_buffer->current_line, line_str);
@@ -345,7 +358,14 @@ ora_dbms_output_put_line(PG_FUNCTION_ARGS)
345358
}
346359
else
347360
{
348-
/* No pending PUT text, just add the line (may be NULL) */
361+
/* No pending PUT text - check line length for direct add */
362+
if (line_len > DBMS_OUTPUT_MAX_LINE_LENGTH)
363+
ereport(ERROR,
364+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
365+
errmsg("ORU-10028: line length overflow, limit of %d bytes per line",
366+
DBMS_OUTPUT_MAX_LINE_LENGTH)));
367+
368+
/* Just add the line (may be NULL) */
349369
add_line_to_buffer(line_str);
350370
}
351371

@@ -358,25 +378,36 @@ ora_dbms_output_put_line(PG_FUNCTION_ARGS)
358378
* Output text without newline (accumulates in current_line).
359379
* Oracle behavior: not retrievable until NEW_LINE or PUT_LINE is called.
360380
* Oracle behavior: NULL is treated as empty string (appends nothing).
381+
* Oracle behavior: raises ORU-10028 if line exceeds 32767 bytes.
361382
*/
362383
Datum
363384
ora_dbms_output_put(PG_FUNCTION_ARGS)
364385
{
365386
char *str;
387+
int str_len;
366388

367389
/* Silently discard if buffer not enabled */
368390
if (output_buffer == NULL || !output_buffer->enabled)
369391
PG_RETURN_VOID();
370392

371393
/* Handle NULL argument - treat as empty string (Oracle behavior) */
372394
if (PG_ARGISNULL(0))
373-
str = "";
374-
else
395+
PG_RETURN_VOID(); /* NULL appends nothing */
396+
375397
{
376398
text *text_arg = PG_GETARG_TEXT_PP(0);
377399
str = text_to_cstring(text_arg);
378400
}
379401

402+
str_len = strlen(str);
403+
404+
/* Check line length limit BEFORE appending (Oracle behavior) */
405+
if (output_buffer->current_line->len + str_len > DBMS_OUTPUT_MAX_LINE_LENGTH)
406+
ereport(ERROR,
407+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
408+
errmsg("ORU-10028: line length overflow, limit of %d bytes per line",
409+
DBMS_OUTPUT_MAX_LINE_LENGTH)));
410+
380411
/* Accumulate in current_line without creating a line yet */
381412
appendStringInfoString(output_buffer->current_line, str);
382413

0 commit comments

Comments
 (0)