Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> RDO 2.0: here is sample for read/write BLOBS

RDO 2.0: here is sample for read/write BLOBS

From: Constantin Olbrich <conzi_at_bln.de>
Date: 1997/09/25
Message-ID: <01bcc9cc$cc464580$ddc1a2c2@conzi-mobil>

Hi RDO/ODBC/Oracle experts!

Reading and Writing Binary Large Objects (BLOBS) to an SQL Server seems to be
difficult in the end 90's. Here is my working framework for MS-Access, MS-SQL 6.5
and Oracle 7.3. This project needs VB5 (SP2) and the ODBC Drivers listed in the
program. My problem is not the functionality, my problem is the time needed for
accessing a BLOB.
My MS-SQL Server reads a 1 MByte File in about 1.2s,

   Ms-Access reads a 1 MByte File in about 5s    Oracle 7.3 reads a 1 MByte File in about 80s (!)

or

   MS-SQL Server reads a 8 MByte File in about 9s,    Ms-Access reads a 8 MByte File in about 12s    Oracle 7.3 reads a 8 MByte File in >> 20 min (I do not wait)

                 (and you never see 100 MByte before year 2000)

My biggest questions:

How can I retrieve an LONG RAW Column in Oracle with VB5 in an acceptable time?
Why is Oracle Call Interface (OCI73 demo program CDEMO3.c) so slow in reading a BLOB? Does somebody have read a BLOB (1..xx MB) from Oracle in normal time?
Do I have to config ORACE 7.3 for better performance in BLOBs?

Constantin Olbrich
microTOOL GmbH
Constantin.Olbrich_at_microtool.de

' ***************************************************
' test suite for read/write an BLOB using RDO 2.0
' ***************************************************
Option Base 1
Option Explicit

Const IsOracle = 1  ' Microsoft ODBC Driver for Oracle 2.00.00.6327
Const IsMSSQL = 2   ' Microsoft ODBC Driver for SQL Server 2.65.0240
Const IsAccess = 3  ' Microsoft Access Driver 3.50.360200

Const ChunkSize = 32768
Public MyDb As Integer
  Private Sub Command1_Click()

     MousePointer = vbHourglass
     
     ' ******** change to your DB **********
     MyDb = IsOracle  ' IsOracle | IsMSSQL | IsAccess
     ' *************************************
     
     Dim env As rdoEnvironment
     Dim cn As rdoConnection
     Dim i As Integer
     Dim mytime As Long
     
     Set env = rdoEngine.rdoEnvironments(0)
     rdoEnvironments(0).CursorDriver = rdUseClientBatch
    
     Select Case MyDb
      Case IsOracle                ' **** use your DSN ****
         Set cn = env.OpenConnection(dsname:="world", _
                                   Connect:="UID=INLRDO;PWD=INLRDO;", _
                                   prompt:=rdDriverNoPrompt)
          Debug.Print "Oracle"
      Case IsMSSQL                 ' **** use your DSN ****
         Set cn = env.OpenConnection(dsname:="INLRDO", _
                                   Connect:="UID=CO;PWD=;", _
                                   prompt:=rdDriverNoPrompt)
          Debug.Print "MS SQL 6.5"
      Case IsAccess                ' **** use your DSN ****
         Set cn = env.OpenConnection(dsname:="access", _
                                   Connect:="UID=;PWD=;", _
                                   prompt:=rdDriverNoPrompt)
         Debug.Print "Access 97"
     End Select
    
     On Error Resume Next
     Debug.Print "Drop table chunktable..."
     cn.Execute "drop table chunktable"

     On Error GoTo 0
     Debug.Print "Creating new table..."
     Select Case MyDb
          Case IsOracle
               cn.Execute "Create table chunktable(int1 int , " & _
                      "char1 char(30), text1 LONG RAW)"
               cn.Execute "create unique index int1index on
chunktable(int1)"
           Case IsMSSQL
               cn.Execute "Create table chunktable(int1 int identity, " & _
                    "char1 char(30), text1 image)"
               cn.Execute "create unique index int1index on
chunktable(int1)"
           Case IsAccess
              cn.Execute "Create table chunktable(int1 int , " & _
                  "char1 char(30), text1 image)"
              cn.Execute "create unique index int1index on
chunktable(int1)"
     End Select

     On Error GoTo 0
     Debug.Print "Begin insert."
     ' put a file some times in chunktable : ********* change for path/file
****
     For i = 1 To 10
       mytime = Timer
       InsertFile "c:\download\sample.txt", i, cn
       Debug.Print "insert duration : ", Timer - mytime
     Next

     Debug.Print "Begin read."
     ' get the file  : ********* change path/filename ************
     For i = 1 To 10
       mytime = Timer
       GetFile "c:\download\smpldnld.txt", i, cn
       Debug.Print "read duration : ", Timer - mytime
     Next
     
     Debug.Print "done."
     MousePointer = vbNormal

  End Sub

   Sub InsertFile(Filename As String, FileNr As Integer, cn As rdoConnection)

     Dim rs As rdoResultset
     Dim currec As Integer
     Dim sqlstr As String
     sqlstr = "Select int1, char1, text1 from chunktable"
     Set rs = cn.OpenResultset(Name:=sqlstr, _
       Type:=rdOpenKeyset, _
       LockType:=rdConcurRowVer)
     rs.AddNew
     rs("int1") = FileNr
     rs("char1") = Now
     rs.Update
     currec = rs("int1")
     rs.Edit
     FileToColumn rs.rdoColumns("text1"), Filename, ChunkSize
     rs("char1") = Now  'need to update at least one non-BLOB column
     rs.Update
     rs.Close

   End Sub
   Sub GetFile(Filename As String, FileNr As Integer, cn As rdoConnection)
     Dim rs As rdoResultset
     Dim sqlstr As String

     ' open cursor again for read a file
     If MyDb = IsAccess Then
       sqlstr = "Select * from chunktable"
     Else
       sqlstr = "Select int1, char1, text1 from chunktable"
     End If
     sqlstr = sqlstr & " where int1 = " + Str$(FileNr)
     Set rs = cn.OpenResultset(Name:=sqlstr, _
       Type:=rdOpenForwardOnly, _
       LockType:=rdConcurReadOnly, _
       Options:=rdFetchLongColumns)
       
       If rs!Int1 <> FileNr Then
         Debug.Print "Error getting text tuple"
       End If
       
       Dim text1_len As Long, image1_len As Long
       If rs("text1").ColumnSize = -1 Then
         Debug.Print "RDO PROBLEM : Your ODBC Driver can't get size of an
BLOB"
       Else
         text1_len = rs("text1").ColumnSize
       End If
       If text1_len = 0 Then
         Debug.Print "RDO PROBLEM : File Length is 0."
       End If
       ColumnToFile rs.rdoColumns("text1"), Filename, _
         ChunkSize, text1_len
       rs.Close

   End Sub    

   Sub ColumnToFile(Col As rdoColumn, ByVal DiskFile As String, _

     BlockSize As Long, ColSize As Long)
     Dim NumBlocks As Integer
     Dim LeftOver As Long
     Dim byteData() As Byte   'Byte array for LongVarBinary
     Dim strData As String    'String for LongVarChar
     Dim DestFileNum As Integer, i As Integer

     ' Remove any existing destination file
     If Len(Dir$(DiskFile)) > 0 Then
       Kill DiskFile
     End If
     
     DestFileNum = FreeFile
     Open DiskFile For Binary As DestFileNum

     NumBlocks = ColSize \ BlockSize
     LeftOver = ColSize Mod BlockSize
     Select Case Col.Type
       Case rdTypeLONGVARBINARY
         byteData() = Col.GetChunk(LeftOver)
         Put DestFileNum, , byteData()
         For i = 1 To NumBlocks
           byteData() = Col.GetChunk(BlockSize)
           Put DestFileNum, , byteData()
         Next i
       Case rdTypeLONGVARCHAR
         For i = 1 To NumBlocks
           strData = String(BlockSize, 32)
           strData = Col.GetChunk(BlockSize)
           Put DestFileNum, , strData
         Next i
         strData = String(LeftOver, 32)
         strData = Col.GetChunk(LeftOver)
         Put DestFileNum, , strData
       Case Else
         MsgBox "Not a ChunkRequired column."
     End Select
     Close DestFileNum

   End Sub

   Sub FileToColumn(Col As rdoColumn, DiskFile As String, _    BlockSize As Long)

     'moves a disk file to a ChunkRequired column in the table
     'A Byte array is used to avoid a UNICODE string
     Dim byteData() As Byte   'Byte array for LongVarBinary
     Dim strData As String    'String for LongVarChar
     Dim NumBlocks As Integer
     Dim filelength As Long
     Dim LeftOver As Long
     Dim SourceFile As Integer
     Dim i As Integer
     SourceFile = FreeFile
     Open DiskFile For Binary Access Read As SourceFile
     filelength = LOF(SourceFile) ' Get the length of the file
     If filelength = 0 Then
       Close SourceFile
       MsgBox DiskFile & " empty or not found."
     Else
       ' Calculate number of blocks to read and left over bytes
       NumBlocks = filelength \ BlockSize
       LeftOver = filelength Mod BlockSize
       Col.AppendChunk Null

       Select Case Col.Type
         Case rdTypeLONGVARCHAR
           ' Read the 'left over' amount of LONGVARCHAR data
           strData = String(LeftOver, " ")
           Get SourceFile, , strData
           Col.AppendChunk strData
           strData = String(BlockSize, " ")
           For i = 1 To NumBlocks
             Get SourceFile, , strData
             Col.AppendChunk strData
           Next i
           Close SourceFile
         Case rdTypeLONGVARBINARY
           ' Read the left over amount of LONGVARBINARY data
           ReDim byteData(LeftOver)
           Get SourceFile, , byteData()
           Col.AppendChunk byteData()
           ReDim byteData(BlockSize)
           For i = 1 To NumBlocks
             Get SourceFile, , byteData()
             Col.AppendChunk byteData()
           Next i
           Close SourceFile
         Case Else
           MsgBox "not a chunkrequired column."
       End Select
     End If

   End Sub Received on Thu Sep 25 1997 - 00:00:00 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US