FormerMember

SQLite OLE

Posted By FormerMember

I found a SQLite3 OLE wrapper that might be useful with VBScript BOI scripts when MS Access and OLE DB isn't an option, SQLite is free and open source.

I used a VB6 demo that came with the control to populate a test.db.

This is an example of reading the data from ScriptBasic.

IMPORT COM.sbi

oSQL = COM::CREATE(:SET, "VBSQLite11.SQLiteConnection")
COM::CBN(oSQL, "OpenDB", :CALL, "Test.db")
DataSet = COM::CBN(oSQL, "OpenDataSet", :CALL, "SELECT ID, szText FROM test_table")
RowCount = COM::CBN(DataSet, "RecordCount", :GET)
FOR i = 0 TO RowCount - 1
  PRINT COM::CBN(DataSet, "ValueMatrix", :GET, i, 0), "_",  COM::CBN(DataSet, "ValueMatrix", :GET, i, 1),"\n"
NEXT
  
COM::RELEASE DataSet
COM::RELEASE oSQL

C:\ScriptBasic\examples>sbc vbsqlite.sb
1_ScriptBasic
2_Sage 100

C:\ScriptBasic\examples>

Table query in SQLite browser / IDE.

SQLite version 3.30.1 2019-10-10 20:19:45
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open test.db
sqlite> select * from test_table;
1|ScriptBasic
2|Sage 100
sqlite>

  • FormerMember
    FormerMember

    This is a more tradition approach to reading the SQLite DB. The first example accessed the table more like a grid. The VBSQLite control isn't documented other than an example in VB6 to show the basic functionality. This is where the ScriptBasic DI (Display Interface) function saves the day.

    IMPORT COM.sbi
    
    oConnection = COM::CREATE(:SET, "VBSQLite11.SQLiteConnection")
    COM::CBN(oConnection, "OpenDB", :CALL, "Test.db")
    oDataSet = COM::CBN(oConnection, "OpenDataSet", :CALL, "SELECT * FROM test_table")
    COM::CBN(oDataSet, "MoveFirst", :CALL)
    DO UNTIL COM::CBN(oDataSet, "EOF", :GET)
      oCols = COM::CBN(oDataSet, "Columns", :GET)
      FOR idx = 1 TO COM::CBN(oCols, "Count", :GET)
        oCol = COM::CBN(oCols, "Item", :GET, idx)
        PRINT COM::CBN(oCol, "Value", :GET), "|"
        COM::RELEASE oCol
      NEXT
      PRINTNL
      COM::RELEASE oCols
      COM::CBN(oDataSet, "MoveNext", :CALL)
    LOOP
    
    COM::RELEASE oDataSet
    COM::RELEASE oConnection

    C:\ScriptBasic\examples>sbc vbsqlite.sb
    1|ScriptBasic|
    2|Sage 100|

    C:\ScriptBasic\examples>

    This is the output from the DI dialogs for the objects used in this example.

    Interface: _SQLiteConnection
    ProgID: VBSQLite11.SQLiteConnection
    CLSID: {0BD93304-488E-421D-B233-22BBB095E955}
    Version: 1.0
    Get Object() As Object
    Get hDB() As Long
    Get Version() As String
    Sub OpenDB(FileName As String, [Mode As SQLiteOpenMode = 2], [SharedCache As Boolean])
    Sub CloseDB()
    Get FileName([DBName As String = main]) As String
    Get ReadOnly([DBName As String = main]) As Boolean
    Get AffectedRows() As Long
    Get LastInsertRowID() As Variant
    Let LastInsertRowID(Variant)
    Get AutoCommit() As Boolean
    Let AutoCommit(Boolean)
    Sub Execute(SQL As String)
    Function OpenDataSet(SQL As String) As Object
    Function CreateCommand(SQL As String) As Object
    Sub BackupDB(Destination As Object, [DestinationDBName As String = main], [SourceDBName As String = main])
    Sub SetProgressHandler(Handler As Object, [VMInstructions As Long = 100])
    
    
    Interface: _SQLiteDataSet                           
    ProgID: VBSQLite11.SQLiteDataSet                    
    CLSID: {A25F662A-FFF7-4B6E-89D1-0584A26AC2DA}       
    Version: 1.0                                        
    Get Object() As Object                              
    Get Columns() As Object                             
    Get RecordCount() As Long                           
    Get Position() As Long                              
    Get ValueMatrix(Row As Long, Col As Long) As Variant
    Get BOF() As Boolean                                
    Get EOF() As Boolean                                
    Sub MoveFirst()                                     
    Sub MoveLast()                                      
    Sub MoveNext()                                      
    Sub MovePrevious()                                  
    Sub Move(NumRecords As Long)   
    
    
    Interface: _SQLiteColumns
    ProgID: VBSQLite11.SQLiteColumns
    CLSID: {4CB2BED1-D7BF-467C-A938-CF630E3BBA4F}
    Version: 1.0
    Get Item(Index As Variant) As Object
    Function Exists(Index As Variant) As Boolean
    Get Count() As Long                     
    
    
    Interface: _SQLiteColumn
    ProgID: VBSQLite11.SQLiteColumn
    CLSID: {D045EB52-5588-4F3E-B6E0-B52E2D1FD236}
    Version: 1.0
    Get Index() As Long
    Get Key() As String
    Get Value() As Variant
    Get Name() As String
    Get TypeName() As String
    Get OriginalName() As String
    Get TableName() As String
    Get DBName() As String
    

  • FormerMember
    FormerMember in reply to FormerMember

    For those that would like to give the VBSQLite OCX a try, I uploaded the project to my Gitlab sandbox repository.

    https://basic-sandbox.us/John/vbsqlite

  • FormerMember
    FormerMember in reply to FormerMember

    The ScriptBasic distribution has a C based extension module for SQLite and requires no other dependencies.

    IMPORT sqlite.sbi
    
    db = sqlite::open("sqlite_demo.db")
    
    sqlite::execute(db,"create table demo (someval integer, sometxt text);")
    sqlite::execute(db,"insert into demo values (123,'hello');")
    sqlite::execute(db, "INSERT INTO demo VALUES (234, 'cruel');")
    sqlite::execute(db, "INSERT INTO demo VALUES (345, 'world');")
    
    stmt = sqlite::query(db,"SELECT * FROM demo")
    WHILE sqlite::row(stmt) = sqlite::SQLITE3_ROW
      IF sqlite::fetchhash(stmt, column) THEN
        PRINT column{"someval"},"\t-\t",column{"sometxt"},"\n"
      END IF
    WEND
    
    sqlite::close(db)
    

    C:\ScriptBasic\examples>sbc sqlite_demo.sb
    123     -       hello
    234     -       cruel
    345     -       world

    C:\ScriptBasic\examples>

  • FormerMember
    FormerMember in reply to FormerMember

    I tried to create a VBScript version of the VBSQLite example done in ScriptBasic. The control is registered so I don't understand the issue VBScript is having. No error # or anything, Just can't do it. Disappointed

    VBScript isn't something I use on a daily basis. I'm not a fan of running in containers, Why I don't use Java.

    ' SQLite3 - VBSQLite Ax using VBScript
    
    Set oConnection = CreateObject ("VBSQLite11.SQLiteConnection")
    oConnection.OpenDB "Test.db"
    Set oDataSet = oConnection.OpenDataSet("SELECT * FROM test_table")
    oDataSet.MoveFirst
    Do Until oDataSet.EOF
      Set oCols = oDataSet.Columns
      For idx = 1 To oCols.Count
        Set oCol =  oCols.Item(idx)
        Wscript.Stdout.Write oCol.Value & "|"
        oCol = Nothing
      Next
      Wscript.Echo
      oCols = Nothing
      oDataSet.MoveNext
    Loop
    oDataSet = Nothing
    oConnection = Nothing
    

    C:\ScriptBasic\examples>cscript //NoLogo vbsqlite.vbs
    C:\ScriptBasic\examples\vbsqlite.vbs(3, 1) Microsoft VBScript runtime error: ActiveX component can't create object: 'VBSQLite11.SQLiteConnection'


    C:\ScriptBasic\examples>

  • in reply to FormerMember

    Did you check your bitness of SQLite and the cscript.exe or wscript.exe that you are using to execute the script?  You may need a shortcut to the correct cscript.exe or wscript.exe and pass the script file as the second argument to it.

    This would be the target for a 32 bit script on a 64 bit system.

    C:\Windows\SysWOW64\wscript.exe "E:\Misc Scripts\ADO Read Text File.vbs"

  • FormerMember
    FormerMember in reply to David Speck

    VBSQLite is an OCX wrapper for a 32 bit version of the SQLite3 C library. Only Wscript Host  has problems creating the object. Every other OLE environment I've tried seems to work fine.

  • in reply to FormerMember

    WSH isn't the only software that is bitness sensitive and considering its age, it doesn't surprise me.  Just look at trying to maintain DSNs on a 64 bit system, the 64 bit program can't be used to create / modify DSN using 32 bit versions of ODBC drivers and vice versa.

  • FormerMember
    FormerMember in reply to David Speck

    I think with using Wscript as a container and another layer from the Windows API is why VBScript is choking on the create. Everything is 32 bit.