@@ -404,6 +404,79 @@ class ThinConnectionImpl extends ConnectionImpl {
404404 }
405405 }
406406
407+ //---------------------------------------------------------------------------
408+ // _populateRowTypeInfo()
409+ //
410+ // Get column and datatype information in case of %ROWTYPE handling.
411+ //---------------------------------------------------------------------------
412+ async _populateRowTypeInfo ( info , options , result ) {
413+ const getColumnsSQL = `
414+ SELECT
415+ column_name,
416+ data_type,
417+ data_type_owner,
418+ case
419+ when data_type in
420+ ('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW')
421+ then data_length
422+ else 0
423+ end,
424+ nvl(data_precision, 0),
425+ nvl(data_scale, 0)
426+ from all_tab_cols
427+ where owner = :owner
428+ and table_name = :name
429+ and hidden_column != 'YES'
430+ order by column_id` ;
431+
432+ const bindVal = [
433+ {
434+ name : "owner" ,
435+ type : types . DB_TYPE_VARCHAR ,
436+ maxSize : 128 ,
437+ dir : constants . BIND_IN ,
438+ values : [ result . outBinds . schema ] ,
439+ } ,
440+ {
441+ name : "name" ,
442+ type : types . DB_TYPE_VARCHAR ,
443+ maxSize : 128 ,
444+ dir : constants . BIND_IN ,
445+ values : [ info . name . substring ( 0 , info . name . length - 8 ) ]
446+ }
447+ ] ;
448+ const val = await this . execute (
449+ getColumnsSQL , 1 , bindVal , options , false
450+ ) ;
451+ try {
452+ const attrRows = await val . resultSet . _getAllRows ( ) ;
453+ info . attributes = [ ] ;
454+ for ( const row of attrRows ) {
455+ const metaData = {
456+ name : row [ 0 ] ,
457+ dataType : row [ 1 ] ,
458+ dataTypeOwner : row [ 2 ] ,
459+ maxSize : row [ 3 ] ,
460+ dataPrecision : row [ 4 ] ,
461+ dataScale : row [ 5 ] ,
462+ } ;
463+ if ( ! metaData . dataTypeOwner ) {
464+ const startPos = row [ 1 ] . indexOf ( '(' ) ;
465+ const endPos = row [ 1 ] . indexOf ( ')' ) ;
466+ if ( endPos > startPos ) {
467+ metaData . dataType = metaData . dataType . substring ( 0 , startPos ) +
468+ metaData . dataType . substring (
469+ endPos + 1 , metaData . dataType . length
470+ ) ;
471+ }
472+ }
473+ this . _addAttr ( info . attributes , metaData ) ;
474+ }
475+ } finally {
476+ val . resultSet . close ( ) ;
477+ }
478+ }
479+
407480 //---------------------------------------------------------------------------
408481 // _populateDbObjectTypeInfo()
409482 //
@@ -449,26 +522,6 @@ class ThinConnectionImpl extends ConnectionImpl {
449522 end if;
450523 end;` ;
451524
452- // get column and datatype information in case of %ROWTYPE handling.
453- const getColumnsSQL = `
454- SELECT
455- column_name,
456- data_type,
457- data_type_owner,
458- case
459- when data_type in
460- ('CHAR', 'NCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW')
461- then data_length
462- else 0
463- end,
464- nvl(data_precision, 0),
465- nvl(data_scale, 0)
466- from all_tab_cols
467- where owner = :owner
468- and table_name = :name
469- and hidden_column != 'YES'
470- order by column_id` ;
471-
472525 const binds = [
473526 {
474527 name : "full_name" ,
@@ -540,78 +593,42 @@ class ThinConnectionImpl extends ConnectionImpl {
540593 errors . throwErr ( errors . ERR_INVALID_OBJECT_TYPE_NAME , name ) ;
541594 }
542595
543- // check cache; if already present, nothing more to do!
544- const info = this . _getDbObjectType ( result . outBinds . schema ,
545- result . outBinds . name , result . outBinds . package_name , result . outBinds . oid ) ;
546- if ( ! info . partial )
547- return info ;
548-
549- // process TDS and attributes cursor
550- if ( info . name . endsWith ( '%ROWTYPE' ) ) {
551- const bindVal = [
552- {
553- name : "owner" ,
554- type : types . DB_TYPE_VARCHAR ,
555- maxSize : 128 ,
556- dir : constants . BIND_IN ,
557- values : [ result . outBinds . schema ] ,
558- } ,
559- {
560- name : "name" ,
561- type : types . DB_TYPE_VARCHAR ,
562- maxSize : 128 ,
563- dir : constants . BIND_IN ,
564- values : [ info . name . substring ( 0 , info . name . length - 8 ) ]
565- }
566- ] ;
567- const val = await this . execute (
568- getColumnsSQL , 1 , bindVal , options , false
569- ) ;
570- const attrRows = await val . resultSet . _getAllRows ( ) ;
571- info . attributes = [ ] ;
572- for ( const row of attrRows ) {
573- const metaData = {
574- name : row [ 0 ] ,
575- dataType : row [ 1 ] ,
576- dataTypeOwner : row [ 2 ] ,
577- maxSize : row [ 3 ] ,
578- dataPrecision : row [ 4 ] ,
579- dataScale : row [ 5 ] ,
580- } ;
581- if ( ! metaData . dataTypeOwner ) {
582- const startPos = row [ 1 ] . indexOf ( '(' ) ;
583- const endPos = row [ 1 ] . indexOf ( ')' ) ;
584- if ( endPos > startPos ) {
585- metaData . dataType = metaData . dataType . substring ( 0 , startPos ) +
586- metaData . dataType . substring (
587- endPos + 1 , metaData . dataType . length
588- ) ;
589- }
590- }
591- this . _addAttr ( info . attributes , metaData ) ;
596+ try {
597+ // check cache; if already present, nothing more to do!
598+ const info = this . _getDbObjectType ( result . outBinds . schema ,
599+ result . outBinds . name , result . outBinds . package_name , result . outBinds . oid ) ;
600+ if ( ! info . partial ) {
601+ return info ;
592602 }
593- } else {
594- info . version = result . outBinds . version ;
595- const attrRows = await result . outBinds . attrs_rc . _getAllRows ( ) ;
596- if ( attrRows . length > 0 ) {
603+
604+ // process TDS and attributes cursor
605+ if ( info . name . endsWith ( '%ROWTYPE' ) ) {
606+ await this . _populateRowTypeInfo ( info , options , result ) ;
607+ } else {
608+ info . version = result . outBinds . version ;
609+ const attrRows = await result . outBinds . attrs_rc . _getAllRows ( ) ;
610+ if ( attrRows . length > 0 ) {
597611 // Its an object not a collection.
598- info . attributes = [ ] ;
599- for ( const row of attrRows ) {
600- const metaData = {
601- name : row [ 1 ] ,
602- dataType : row [ 3 ] ,
603- dataTypeOwner : row [ 4 ] ,
604- packageName : row [ 5 ] ,
605- oid : row [ 6 ]
606- } ;
607- this . _addAttr ( info . attributes , metaData ) ;
608- }
612+ info . attributes = [ ] ;
613+ for ( const row of attrRows ) {
614+ const metaData = {
615+ name : row [ 1 ] ,
616+ dataType : row [ 3 ] ,
617+ dataTypeOwner : row [ 4 ] ,
618+ packageName : row [ 5 ] ,
619+ oid : row [ 6 ]
620+ } ;
621+ this . _addAttr ( info . attributes , metaData ) ;
622+ }
609623
624+ }
625+ await this . _parseTDS ( result . outBinds . tds , info ) ;
610626 }
611- await this . _parseTDS ( result . outBinds . tds , info ) ;
627+ info . partial = false ;
628+ return info ;
629+ } finally {
630+ result . outBinds . attrs_rc . close ( ) ;
612631 }
613- info . partial = false ;
614- return info ;
615632
616633 }
617634
0 commit comments