DbObjectOra(3NS)

NAME SYNOPSIS DESCRIPTION IMPLEMENTATION NOTES WARNINGS SEE ALSO AUTHORS

NAME

DbObjectOra - This object serves as an interface between the object-oriented entity classes and the relational database. All object data is represented as a tcl array. This class translates between that array and the sybtcl input and output to the relational database.

SYNOPSIS

DbObjectOra
handle
_dbuser
_dbpass
_dsquery
handleIndex
numHandles
waitInterval 30
tranFlag

Standard Public Interface

DbObjectOra::Connect { {dbuser{}} {dbpass{}} {dsquery {}} } : newHandleNumber
DbObjectOra::Close { } : closedHandleNumber
DbObjectOra::SetHandle { {handle} } : currentHandleIndex
DbObjectOra::Query { class objref {where {}} {order {}} }
DbObjectOra::Cancel { class objref }
DbObjectOra::Next { class objref } : 1(Success), 0(Failure)
DbObjectOra::Count { class {where {}} {distinct *} } : count
DbObjectOra::Insert { class objref } : oid
DbObjectOra::Update { class objref }
DbObjectOra::Delete { class objref }
DbObjectOra::Begin { }
DbObjectOra::Commit { }
DbObjectOra::Rollback { }
DbObjectOra::Sql { sqlString }
DbObjectOra::Nextrow { } : raw row

Private Interface


DbObjectOra::BuildType { type value } : formattedValue
DbObjectOra::BuildUpdate { class objref } : updateClause
DbObjectOra::BuildSelect { class objref } : selectClause
DbObjectOra::BuildInsert { class objref } : insertAttrclause
DbObjectOra::BuildValue { class objref } : insertValueClause
DbObjectOra::BuildWhere { class where } : whereClause
 

DESCRIPTION

DbObjectOra::Connect

This procedure makes a connection to the database using the given dbuser, dbpass, and dsquery information. This same procedure can also be used to open multiple handles. If after the first invocation, no information is given, it will open another connection using the same information as given for the first handle. It returns the integer handle that is opened.

Inputs:
dbuser - (optional on 2nd invocation) - the login for the database
dbpass - (optional on 2nd invocation) - The password for the database
dsquery - ( optional database server). If none is provided, the DSQUERY environment variable is used.
Outputs:
handle(n) - an array of database connections
Returns:
handle - [1, 2 ....n] - An integer specifying a handle opened by this command.

DbObjectOra::Close

This procedure closes the sybase connection of the highest number handle and returns that closed handle. Any variable used to hold that handle is unset.

Inputs: None
Outputs: None
Returns:
handle - [0, 1, 2 ....n] - An integer specifying a handle closed by this command

DbObjectOra::SetHandle

This procedure set the current handle to the given handle and the current handle is returned. This remains the current handle until another DbObjectOra::SetHandle is issued or that handle is closed. If no handle parameter is given, the current handle is returned.

Inputs:
handle - [1, 2 ......] - (optional) - A handle to set as the current handle.
Outputs: None
Returns:
handle - [0, 1, 2 ....n] - An integer specifying a the current handle

DbObjectOra::Begin

This procedure begins a transaction on the private variable handle. It enforces single layer transactions, preventing nesting.

Inputs: None
Outputs: None
Returns: None

DbObjectOra::Commit

This procedure commits a transaction on the private variable handle.

Inputs: None
Outputs: None
Returns: None

DbObjectOra::Rollback

This procedure rolls back a transaction on the private variable handle. Since only single layer transactions are supported, it is important that control is returned immediately to the original transaction beginning. In doing this, rollback can be called multiple times without ill effect.

Inputs: None
Outputs: None
Returns: None

DbObjectOra::Query

This procedure sets up a query that may involve a join across multiple tables, depending on how the object is defined. The given objref array specifies the attributes that are to be retrieved. The where clause and order by clause specify the filtering and ordering of the retrieved results. Since the where and order clauses are raw SQL strings, the application programmer is encouraged to define new member procedures so these SQL specifications remain private to this object. Note, the same objref given to this procedure must be used to retrieve the results with DbObjectOra::Next.

Inputs:
class - The entity class to operate on
objref - A reference to an entity array representing the object instance. The attributes specified become the select list in the SQL, meaning only those values are returned in the query
where - [default {}] - the where string for the SQL statement. This is a raw where clause that does not include join constraints. All column names and values are database specific
order - [default {}] - the orderby clause for the SQL statement. All column names are database specific.
Outputs: None
Returns: None

DbObjectOra::Next

This procedure retrieves the query results and places them in the objref array.. It is important that the given objref array is the same as the array used in DbObjectOra::Query since the attributes given in the array determine what attributes get loaded with the returned values. Each attribute is given the value returned by the query and an oid is also assigned if the return code is 1.

Inputs:
class - The entity class to operate on
objref - A reference to an entity array representing the object instance. Only the values of the attributes given in the array are populated in the database.
Outputs:
objref - A reference to an entity array representing the object instance given to tail::Query. Each attribute is given the value returned by the query and an oid is also assigned if the return code is 1.
Returns:
1 - A row is available; 0 - No rows returned.

DbObjectOra::Count

This procedure counts the rows that match the given where statement. A key can be passed that is unique on the primary table in the case of a join to allow the count to be distinct. It

  1. If no distinct key is given, the select statement is set to count(*)
  2. If a key is given, the select clause is set to count(distinct $distinct)
  3. Build the sequel string by concatenating the select, from and where clauses. The where clause is built by calling DbObjectOra::BuildWhere
  4. Send of the query by calling DbObjectOra::Sql
  5. Retrieve the count by calling DbObjectOra::Nextrow and return this result
Inputs:
class - The entity class to operate on
where - [default {}] - the where string for the SQL statement. This is a raw where clause that does not include join constraints. All column names and values are database specific
distinct - [default *] - A key that is to be counted distinctly. This is used when a join returns multiple rows for a unique key in the primary table. these rows would be counted as one when the key is specified.
Outputs: None
Returns:
count - The count result

DbObjectOra::Cancel

This procedure cancels the result of a query. It is used to discard unretrieved results if they are unneeded.

Inputs: None
Outputs: None
Returns: None

DbObjectOra::Insert

This procedure inserts the object into the database. It only inserts into one table, so each attribute in the objref array must belong to that table or an error will be generated. Only the attributes that are given in the objref array are inserted. If a table contains attributes that are not given and they do not accept null, an error will be generated The oid is returned. It

  1. Builds the attribute list using DbObjectOra::BuildInsert
  2. Builds the valueList using DbObjectOra::BuildValue
  3. Contructs the sql string using the constructed attribute list and value list.
  4. Issues the insert using DbObjectOra::Sql
  5. If the table contains the primary key, retrieve the identity value by calling DbObjectOra::Sql and return it as an oid.
Inputs:
class - The entity class to operate on
objref - A reference to an entity array representing the object instance. Only the values of the attributes given in the array are populated in the database.
Outputs:
objref(oid) - the unique identifier for the object
Returns:
oid - the unique identifier for the object.

DbObjectOra::Update

This procedure updates the object represented by the given objref array. This array must contain a valid oid. Only the values of the attributes represented in the array are updated in the database so parts of the object can be updated. This procedure performs the update to only one table as indicated in the entity this(table) variable. Therefore, all parameters in objref must belong to this table or an error will occur.

Inputs:
class - The entity class to operate on
objref - A reference to an entity array representing the object instance. Only the values of the attributes given in the array are updated in the database.
Outputs: None
Returns: None

DbObjectOra::Delete

This procedure deletes the object represented by the given objref array. The only required attribute is the oidsince this tells the procedure which object to delete.

Inputs:
class - The entity class to operate on
objref - A reference to an entity array representing the object instance.
Outputs: None
Returns: None

DbObjectOra::Sql

This procedure issues a Sybase sql request. If a timeout (in seconds) is given, it will return to the Tcl event loop every timeout seconds.

Inputs:
sqlString - the Sybase sql string
timeout -(in seconds) [default -1] - This procedure blocks until the Sybase server satisfies the request. However, if a timeout, in seconds, is specified, Tcl will return to the event loop every timeout seconds.
Outputs: None
Returns: None

DbObjectOra::Nextrow

This procedure retrieves the sybase row from the private handle connection..

Inputs:
Outputs: None
Returns:
nextrow - The next sybase row of a given sql search. It returns {} if no row is present.

DbObjectOra::BuildWhere

This procedure concatenates the given where clause with any internal entity where clause and returns the final string. If the entity has no internal where clause, the given clause is simply returned.

Inputs:
class - The entity class to operate on
where - The given SQL where string
Outputs: None
Returns:
whereClause - Returns the final where clause.

DbObjectOra::BuildType

This procedure formats the given value according to the given type. If the type is an integer, return the given value without modification. If it is a text or datetime type, return the value enclosed in single quotes. If the keyword function is used, the value after the keyword is simply returned. This allows the use of the sybase functions. If any parameter is specified as {} or "", it will be recorded in the database as a null. Nulls are returned as {}.

Inputs:
type - [Text, Datetime, EnumText, Integer, EnumInt] - the type of the given value
value - The value to be formatted
Outputs: None
Returns:
Returns either 'value' or value depending on type

DbObjectOra::BuildUpdate

This procedure builds the SQL update string . Only the attributes found in objref are built in the list. the oid is not included

  1. For each attribute in objref, find the type by calling Entity::GetAttribute
  2. Format the value according to the type by calling DbObjectOra::BuildType
  3. Create the update clause and concatenate each "attribute=value" adding the commas between expressions.
  4. Return the completed update clause, "attr1=value1, attr2='value2', etc" The quotes depend on attribute type.
Inputs:
class - The entity class to operate on
objref - The array reference that represents the entity object instance.
Outputs: None
Returns:
Returns the "attr1=value1, attr2='value2', etc" The quotes depend on attribute type

DbObjectOra::BuildSelect

This procedure builds the SQL select clause used in an SQL query string. Only the attributes found in objref are built in the list. The oid is not included.

  1. For each attribute in objref, find the database aliased column name by calling Entity::GetAttribute
  2. Create the select clause and concatenate each value adding the commas between values.
  3. Return the completed select clause, "t.attr1, e.attr2, etc"
Inputs:
class - The entity class to operate on
objref - The array reference that represents the entity object instance.
Outputs: None
Returns:
SQL select List - Returns the aliased column name "t.attr1, e.attr2, etc"

DbObjectOra::BuildInsert

This procedure builds the SQL attribute list used in an SQL insert string. Only the attributes found in objref are built in the list. the oid is not included.

  1. For each attribute in objref, create the attribute list and concatenate each attribute adding the commas between attributes.
  2. Return the completed insert clause, "attr1, attr2, etc"
Inputs:
class - The entity class to operate on
objref - The array reference that represents the entity object instance.
Outputs: None
Returns:
SQL insert list - Returns the "attr1, attr2, etc"

DbObjectOra::BuildValue

This procedure builds the SQL value list used in an SQL insert string. Only the values of the attributes found in objref are built in the list. The oid is not included

  1. For each attribute in objref, find the type by calling Entity::GetAttribute
  2. Format the value according to the type by calling DbObjectOra::BuildType
  3. Create the valueClause and concatenate each value adding the commas between values.
  4. Return the completed value clause, "value1, 'value2', etc". The quotes depend on attribute type
Inputs:
class - The entity class to operate on
objref - The array reference that represents the entity object instance.
Outputs: None
Returns:
SQL value list - Returns the "value1, 'value2', etc" The quotes depend on attribute type

DIAGNOSTICS

procName

The following messages will be logged.

message1
Explanation
message2
Explanation

IMPLEMENTATION

namespace eval DbObjectOra {
   # this is the logon handle. 
   variable handle

   # this is the statement handle. 
   variable sth
   variable sqlString
   variable _dbuser
   variable _dbpass
   variable _dsquery
   variable handleIndex 0
   variable numHandles 0
   variable waitInterval 30
   variable minSleepInterval 5
   variable tranflag
   variable lda 
}

DbObjectOra::Connect

proc DbObjectOra::Connect { {dbuser {}} {dbpass {}} {dsquery {}}} {
     variable handle
     variable _dbuser
     variable _dbpass
     variable _dsquery
     variable handleIndex
     variable numHandles 0
     variable sth 
     variable tranflag
     global env scriptName

     logEntryLS DbgEntryExit "Entering DbObjectOra::Connect"

         #Save the given information the first time 
     if {$numHandles == 0} {
          #dbuser and dbpass must be given 
      if {[string equal $dbuser {}]} {
	 if [catch {set dbuser $env(DBUSER)} result ] {
	    error "DbObjectOra::Connect failed: $result"
         }
      }

      if {[string equal $dbpass {}]} {
	 if [catch {set dbpass $env(DBPASS)} result ] {
	    error "DbObjectOra::Connect failed: $result"
         }
      }

      set _dbuser $dbuser
      set _dbpass $dbpass
      set _dsquery $dsquery
   } else {
      if {[string compare $dbuser {}] == 0 || [string compare $dbpass {}] == 0} {
         set dbuser $_dbuser
         set dbpass $_dbpass
      }
   }

   set login "$dbuser/$dbpass$dsquery"
        #Open the database Connection as asynchronous
   if {[string compare $dsquery {}] == 0} {
      if [ catch {
            #set handle([incr DbObjectOra::numHandles]) [oralogon $login -async]
	    # logon to system in synchonous mode. 
            set handle([incr DbObjectOra::numHandles]) [oralogon $login]
	    set sth [oraopen $handle($numHandles)]
               #Only set this the first time 
            if {$numHandles == 1} {
               set handleIndex 1
            }
               #Initialize the transaction for the new connection 
            set tranflag($numHandles) 0

	    DbObjectOra::Begin 
      } result ] {
         error "DbObjectOra::Connect: Connect Failed: $result"
         return $numHandles
      }
   } else {
      if [ catch {
            set handle([incr numHandles]) [oralogon $login]
	    set sth [oraopen $handle($numHandles)]
               #Only set this the first time 
            if {$numHandles == 1} {
               set handleIndex 1
            }

               #Initialize the transaction for the new connection 
            set tranflag($numHandles) 0
	    DbObjectOra::Begin
      } result ] {
         error "DbObjectOra::Connect: Connect Failed: $result"
         return $numHandles
      }
   }
         #Initialize the transaction for the new connection 
    set tranflag($numHandles) 0

         #This variable must be set to retrieve any binary data as hex.
   #set oramsg(binaryashex) 1
   #set oramsg(nullvalue) {}
   logEntryLS DbgEntryExit "Exiting DbObjectOra::Connect with handle, $handle($handleIndex)"
   return $numHandles
}

DbObjectOra::Close

proc DbObjectOra::Close {} {
     variable handle
     variable handleIndex
     variable numHandles

     if {$numHandles == 0} {return $numHandles}

     logEntryLS DbgEntryExit "Entering DbObjectOra::Close"
     set closedHandle $numHandles

     catch {
        oraclose $handle($numHandles)
        unset handle($numHandles)
        if {$handleIndex == $numHandles} {incr DbObjectOra::handleIndex -1}
        incr DbObjectOra::numHandles -1
     }

     logEntryLS DbgEntryExit "Exiting DbObjectOra::Close"
     return $closedHandle
}

DbObjectOra::SetHandle

proc DbObjectOra::SetHandle { {index {}} } {
     variable handle
     variable dbuser
     variable dbpass
     variable dsquery
     variable handleIndex
     variable numHandles

         #Is this a read accessor? 
     if {[string compare $index {}] == 0} {return $handleIndex}

     logEntryLS DbgEntryExit "Entering DbObjectOra::SetHandle"

     if {$index > $numHandles || $index <= 0} {
        error "DbObjectOra::SetHandle: The requested handle does not exist"
        return $handleIndex
     }

     set handleIndex $index

     logEntryLS DbgEntryExit "Exiting DbObjectOra::SetHandle"
     return $handleIndex
}

DbObjectOra::BuildType

proc DbObjectOra::BuildType {type value} {

        #Include the ability to specify characteristic functions 
     if {[string compare [lindex $value 0] function] == 0} {
        return [lindex $value 1]
     }

          #Include the ability to specify null values
     if {[string compare $value {}] == 0} {
        return null
     }

     switch -- $type {
       Text -
       Datetime {return '$value'}
       EnumText {return '[Entity::Terse $value]'}
       Binary { return [format "%#8.8x" $value] }
       Integer {return $value}
       EnumInt {return [Entity::Terse $value]}
       default {return {}}
     }
}

DbObjectOra::BuildValue

proc DbObjectOra::BuildValue {class objref} {
     upvar $objref obj

     logEntryLS DbgEntryExit "Entering DbObjectOra::BuildValue"

         #Used in insert to build the value list
     foreach attr [array names obj] {

     set type [Entity::GetAttribute $class $attr type]

     if {[info exists valueClause] == 0} {
        set valueClause [DbObjectOra::BuildType $type $obj($attr)]
     } else {
        set valueClause [cconcat $valueClause ", [DbObjectOra::BuildType $type $obj($attr)]"]
     }
   }

   logEntryLS DbgAll "DbObjectOra::BuildValue valueClause: $valueClause"
   logEntryLS DbgEntryExit "Exiting DbObjectOra::BuildValue"

   return $valueClause
}

DbObjectOra::BuildUpdate

proc DbObjectOra::BuildUpdate {class objref} {
     upvar $objref obj

     logEntryLS DbgEntryExit "Entering DbObjectOra::BuildUpdate"

     set updateClause {}

        #This prepares the update list for an update 

          #Skip the mdt, dt 

     if { [info exists obj(mdt)] } { set tmp_oid $obj(mdt); unset obj(mdt) }
     if { [info exists obj(dt)] }  { set tmp_oid $obj(dt); unset obj(dt) }

     foreach attr [array names obj] {

           #Retrieve the attribute column name and remove the alias 
      set column [Entity::GetAttribute $class $attr column]
      #set column [lindex [split $column .] 1]

      set type [Entity::GetAttribute $class $attr type]

      if {[string compare $updateClause {}] == 0} {
         set updateClause "$column = [DbObjectOra::BuildType $type $obj($attr)]"
      } else {
         set updateClause [cconcat $updateClause ", $column = [DbObjectOra::BuildType $type $obj($attr)]"]
      }
   }

   if { [info exists tmp_mdt] } { set $obj(oid) $tmp_mdt}
   if { [info exists tmp_dt] }  { set $obj(oid) $tmp_dt}

   logEntryLS DbgAll "DbObjectOra::BuildUpdate updateClause: $updateClause"
   logEntryLS DbgEntryExit "Exiting DbObjectOra::BuildUpdate"

   return $updateClause
}

DbObjectOra::BuildWhere

proc DbObjectOra::BuildWhere {class where} {
     upvar #0 $class\::this this

     logEntryLS DbgEntryExit "Entering DbObjectOra::BuildWhere"

          #This builds the where clause for the Query 
     if {[string compare $this(where) {}] != 0} {
        if {[string compare $where {}] == 0} {
           return $this(where)
        } else {
           return "$this(where) and $where"
        }
     }

     logEntryLS DbgAll "DbObjectOra::BuildWhere whereClause: $where"
     logEntryLS DbgEntryExit "Exiting DbObjectOra::BuildWhere" 

     return $where
}

DbObjectOra::BuildSelect

proc DbObjectOra::BuildSelect {class objref} {
     upvar $objref obj
     variable sth

     set selectClause {}

     logEntryLS DbgEntryExit "Entering DbObjectOra::BuildSelect"

     foreach attr [array names obj] {
           #Skip the oid 
        if {[string compare oid $attr] == 0} {continue}

        if {[string match $selectClause {} ]} {
	   set selectClause [Entity::GetAttribute $class $attr column]
        } else {
           set selectClause [cconcat $selectClause ", [Entity::GetAttribute $class $attr column]"]
        }
     }

     logEntryLS DbgAll "DbObjectOra::BuildSelect selectClause: $selectClause"
     logEntryLS DbgEntryExit "Exiting DbObjectOra::BuildSelect"

     return $selectClause
}

DbObjectOra::BuildInsert

proc DbObjectOra::BuildInsert {class objref} {
     upvar $objref obj
     upvar #0 $class\::attr classAttr

     logEntryLS DbgEntryExit "Entering DbObjectOra::BuildInsert"

        #This builds the select clause for both select and insert 
     foreach attr [array names obj] {
          #Retrieve the attribute column name and remove the alias 
        set column [Entity::GetAttribute $class $attr column]
        set column [lindex [split $column .] 1]
        if {[info exists insertClause] == 0} {
           set insertClause $column
        } else {
           set insertClause [cconcat $insertClause ", $column"]
        }
     }

     logEntryLS DbgAll "DbObjectOra::BuildInsert insertClause: $insertClause"
     logEntryLS DbgEntryExit "Exiting DbObjectOra::BuildInsert"

     return $insertClause
}

DbObjectOra::Query

proc DbObjectOra::Query { class objref {where {}} {order {}} } {
     variable waitInterval
     variable tranflag 
     upvar $objref obj
     upvar #0 $class\::this this
     upvar #0 $class\::attr attr
     variable sth

     logEntryLS DbgEntryExit "Entering DbObjectOra::Query"

     set oidColumn [Entity::GetAttribute $class oid column]

       #filter out any attributes not belonging to this class 
     array set filteredObj [Entity::ArrayCopy $class obj] 

     set selectString [DbObjectOra::BuildSelect $class filteredObj]

     if [string match $selectString {} ] {
        set sqlString "select $oidColumn"
     } else {
        set sqlString "select $oidColumn, $selectString"
     }

     set sqlString [cconcat $sqlString " from $this(from)"]
     set where [DbObjectOra::BuildWhere $class $where]

     if {[string compare $where {}] != 0} {set sqlString [cconcat $sqlString " where $where"]}
     if {[string compare $order {}] != 0} {set sqlString [cconcat $sqlString " order by $order"]}

     logEntryLS DbgMsg "DbObjectOra::Query SqlString: $sqlString"

     if [catch {DbObjectOra::Sql $sqlString $waitInterval} result] {
        error "DbObjectOra::Query: $result  "
     }
}

DbObjectOra::GetListOf

proc DbObjectOra::GetListOf { class attr {where {}} {order {}} } {
     variable waitInterval
     variable sth 

     upvar #0 $class\::this this
 
     logEntryLS DbgEntryExit "Entering DbObjectOra::GetListOf"

     set valueList {}
     set selectString [Entity::GetAttribute $class $attr column]
     set sqlString "select distinct $selectString"
     set sqlString [cconcat $sqlString " from $this(from)"]
     set where [DbObjectOra::BuildWhere $class $where]

     if {[string compare $where {}] != 0} {set sqlString [cconcat $sqlString " where $where"]}
     if {[string compare $order {}] != 0} {set sqlString [cconcat $sqlString " order by $order"]}

     logEntryLS DbgMsg "DbObjectOra::Count SqlString: $sqlString"

     if [catch {
        DbObjectOra::Sql $sqlString $waitInterval
        set option -datavariable
        set row [DbObjectOra::Orafetch $sth $option] 

        while {[llength $row] > 0} {
           lappend valueList [lindex $row 0]
	   set row [DbObjectOra::Orafetch $sth $option]
        }
     } result] {
        error "DbObjectOra::GetListOf: $result: $result"
     }

     return $valueList
}

DbObjectOra::Count

proc DbObjectOra::Count { class {where {}} {distinct *} } {
     variable waitInterval
     upvar #0 $class\::this this

     logEntryLS DbgEntryExit "Entering DbObjectOra::Count"

     if {[string match $distinct *]} {
        set sqlString "select count(*)"
     } else {
        set sqlString "select count(distinct $distinct)"
     }

     set sqlString [cconcat $sqlString " from $this(from)"]
     set where [DbObjectOra::BuildWhere $class $where]

     if {[string compare $where {}] != 0} {set sqlString [cconcat $sqlString " where $where"]}

     logEntryLS DbgMsg "DbObjectOra::Count SqlString: $sqlString"

     if [catch {
        DbObjectOra::Sql $sqlString $waitInterval
        set count [DbObjectOra::Nextrow]
     } result] {
        error "DbObjectOra::Count: $result: "
     }

     return $count 
}

DbObjectOra::Next

proc DbObjectOra::Next { class objref } {
     upvar $objref obj
     variable handle 
     variable handleIndex 
     variable sth

     logEntryLS DbgEntryExit "Entering DbObjectOra::Next"

        #filter out any attributes not belonging to this class 
     array set filteredObj [Entity::ArrayCopy $class obj] 


        #Do the initial fetch.
     set option -datavariable
     set row [DbObjectOra::Orafetch $sth $option] 

     logEntryLS DbgMsg "Returned Row: $row"

        # Determine if you are at the end of the file. 
     if {![cequal [oramsg $sth rc] 1403]} {
        foreach rowIn $row {
           set obj(oid) [lindex $rowIn 0]
           set i 1
           foreach attr [array names filteredObj] {
                 # Skip the oid 
              if {[string compare oid $attr] == 0} {continue}
                   # Check for binary 
              switch -- [Entity::GetAttribute $class $attr type] {
                 Binary { set obj($attr) [join [list 0x [string trim [lindex $row $i]]] {}] }
                 EnumText -
                 EnumInt { set obj($attr) [Entity::EnumValue [Entity::GetAttribute $class $attr enum] [lindex $row $i]] }
                default { set obj($attr) [lindex $row $i] }
              }
              incr i
           }

           logEntryLS DbgEntryExit "Exiting DbObjectOra::Next after retrieving oid, $obj(oid) "
           return 1
       }
     } else {
        logEntryLS DbgEntryExit "Exiting DbObjectOra::Next: No row retrieved"
        return 0 
     }
}

DbObjectOra::Oraparse

proc DbObjectOra::Oraparse { stmHandle sqlString } {
     variable handle
     variable handleIndex

     catch { [oraparse $stmHandle $sqlString] } 
     if {![oramsg $handle($handleIndex) rc] == 0} {
          error "DbObjectOra::Oraparse: $error $sqlString "
     } 
}

DbObjectOra::Orafetch

proc DbObjectOra::Orafetch { stmHandle {option {}} } {
     variable handle
     variable handleIndex

     set rowsRtn {}

     if {[cequal $option {}]} {
         catch {orafetch $stmHandle}
     } else { 
         catch {orafetch $stmHandle $option rowsRtn}
     }

     if {!([oramsg $handle($handleIndex) rc] == 0 || [ormsg $handle($handleIndex) rc] == 1403)} {
        error "DbObjectOra::Orafetch: $error "
     } 

     return $rowsRtn
}

DbObjectOra::Oraexec

proc DbObjectOra::Oraexec { stmHandle } {
     variable handle
     variable handleIndex

     catch {oraexec $stmHandle}
     if {![oramsg $handle($handleIndex) rc] == 0} {
	 DbObjectOra::Rollback 
        error "DbObjectOra::Oraexec: $error $stmHandle"
     } else {
         DbObjectOra::Commit 
     }
}

DbObjectOra::Cancel

proc DbObjectOra::Cancel {} {
     variable handle
     variable handleIndex
     variable numHandles

     if {$numHandles != 0} {
        oracancel $handle($handleIndex)
     }
}

DbObjectOra::Insert

proc DbObjectOra::Insert { class objref } {
     variable handle
     variable handleIndex
     variable waitInterval
     variable sth
     variable sqlString

     upvar $objref obj
     upvar #0 $class\::this this

     logEntryLS DbgEntryExit "Entering DbObjectOra::Insert"

     set attrList [DbObjectOra::BuildInsert $class obj]
     set sqlString "select ip_oid.nextval from DUAL " 

     DbObjectOra::Oraparse $sth $sqlString
     DbObjectOra::Oraexec $sth

     set option -datavariable
     set obj(oid) [DbObjectOra::Orafetch $sth $option] 

       # Because you have to do a nextval to make currval work, the nextval
          # must be decremented by 1 to reflect the currval. 
     set obj(oid) [incr obj(oid) -1]

     set valueList [DbObjectOra::BuildValue $class obj]

     set sqlString "insert into [lindex $this(table) 0] ($attrList) values ($valueList)"

     logEntryLS DbgMsg "DbObjectOra::Insert SqlString: $sqlString"
     if [ catch { DbObjectOra::Sql $sqlString $waitInterval } result ] { 
         error "DbObjectOra::Insert: $result: "
     }

     logEntryLS DbgEntryExit "Exiting DbObjectOra::Insert with oid, $obj(oid)"
     return $obj(oid) 
}

DbObjectOra::Update

proc DbObjectOra::Update {class objref} {
     variable waitInterval
     variable sth 
     upvar $objref obj
     upvar #0 $class\::this this

     logEntryLS DbgEntryExit "Entering DbObjectOra::Update"

     set setList [DbObjectOra::BuildUpdate $class obj]

        #If there is no setlist, we are done 
     if {[string compare $setList {}] == 0} { return }

     set where "[Entity::GetAttribute $class oid column] = $obj(oid)"
     set sqlString "update $this(table) set $setList where $where"

     logEntryLS DbgMsg "DbObjectOra::Update SqlString: $sqlString"

     if [ catch { DbObjectOra::Sql $sqlString $waitInterval} result ] { 
         error "DbObjectOra::Update: $result: "
     }

     logEntryLS DbgEntryExit "Exiting DbObjectOra::Update"
}

DbObjectOra::Delete

proc DbObjectOra::Delete {class objref} {
     variable waitInterval
     variable sth 

     upvar $objref obj
     upvar #0 $class\::this this

     logEntryLS DbgEntryExit "Entering DbObjectOra::Delete"

     set where "[Entity::GetAttribute $class oid column] = $obj(oid)"
     set sqlString "delete from $this(table) where $where"

     logEntryLS DbgMsg "DbObjectOra::Delete SqlString: $sqlString"

     if [ catch { DbObjectOra::Sql $sqlString $waitInterval} result ] { 
         error "DbObjectOra::Delete: $result: "
     }

     logEntryLS DbgEntryExit "Exiting DbObjectOra::Delete"
}

DbObjectOra::Begin

proc DbObjectOra::Begin {} {
     variable waitInterval
     variable tranflag
     variable handleIndex
     variable sth

     logEntryLS DbgEntryExit "Entering DbObjectOra::Begin"

     set sqlStatement "set transaction use rollback segment " 

     if {$tranflag($handleIndex) == 0} {
        if [catch {DbObjectOra::Sql $sqlStatement $waitInterval} result] {
           error "DbObjectOra::Begin: $result: "
	   return
        }
     }

    incr tranflag($handleIndex)
  
    logEntryLS DbgMsg "Begin Transaction"
    logEntryLS DbgEntryExit "Exiting DbObjectOra::Begin"
}

DbObjectOra::Commit

proc DbObjectOra::Commit {} {
     variable waitInterval
     variable tranflag
     variable handleIndex
     variable handle
     variable this 

     logEntryLS DbgEntryExit "Entering DbObjectOra::Commit"


     if {$tranflag($handleIndex) == 1} {
        catch {oracommit $handle($handleIndex)}
         if {![oramsg $handle($handleIndex) rc] == 0} {
             error "DbObjectOra::Insert oracommit: $rc "
             error "DbObjectOra::Insert Commit table: [lindex $this(table) 0] "
         } 
     }

     if {$tranflag($handleIndex) > 0 } {
        incr tranflag($handleIndex) -1
     }
   
     logEntryLS DbgMsg "Commit Transaction"
     logEntryLS DbgEntryExit "Exiting DbObjectOra::Commit"
}

DbObjectOra::Rollback

proc DbObjectOra::Rollback {} {
     variable waitInterval
     variable tranflag
     variable handleIndex
     variable handle
     variable sth 
     variable this 

     logEntryLS DbgEntryExit "Entering DbObjectOra::Rollback"

     if {$tranflag($handleIndex) > 0} {
         catch {oraroll $handle($handleIndex)}
         if {![oramsg $handle($handleIndex) rc] == 0} {
            error "DbObjectOra::Oraroll: $error "
	    return
         } 
         set tranflag($handleIndex) 0
     }

     logEntryLS DbgMsg "Rollback Transaction"
     logEntryLS DbgEntryExit "Exiting DbObjectOra::Rollback"
}

DbObjectOra::Sql

proc DbObjectOra::Sql {sqlString {timeout -1}} {
     variable handle
     variable handleIndex
     variable minSleepInterval
     variable sth 

     logEntryLS DbgEntryExit "Entering DbObjectOra::Sql $sqlString, $timeout"
     logEntryLS DbgMsg "DbObjectOra::Sql SqlString: $sqlString"

     set start [clock seconds]
     set numDeadlocks 0

       #A timeout of -1 is equivalent to synchronous
          #If not -1, it is a timeout in seconds 
     if {[string compare $timeout -1] != 0} {
        set msInterval [expr $timeout * 1000]
     } else {set msInterval -1}

     catch { [orasql $sth $sqlString] } 

     if {[oramsg $handle($handleIndex) rc] == 00500} {
          set deadlockFlag 1
          set tranflag($handleIndex) 0 
          logEntryLS Error "DbObjectOra::Sql: Encountered Oracle deadlock error ORA-0050"                 
          error "DbObjectOra::OraSql: $rc $sqlString "
     }

     DbObjectOra::Oraparse $sth $sqlString
     DbObjectOra::Oraexec $sth

   logEntryLS DbgEntryExit "Exiting DbObjectOra::Sql $sqlString, $timeout"
}

DbObjectOra::Nextrow

proc DbObjectOra::Nextrow {} {
     variable handle
     variable sth 
     variable handleIndex
     global oramsg
     set option -datavariable

     set row [DbObjectOra::Orafetch $DbObjectOra::sth $option]
     return $row
}

EXAMPLES

NOTES

WARNINGS

SEE ALSO


AUTHORS

by Timothy L. Eshelman