Store message in SQLite table

Clovertech Forums Read Only Archives Cloverleaf Cloverleaf Store message in SQLite table

  • Creator
    Topic
  • #52359
    Jerry Tilsley
    Participant

      All,

      I am trying to store some messages into an SQLite table via TCL, but the messages as a whole are not going in, or maybe SQLite is just not pulling them back out correctly.

      Am I missing an escape or something?

      Code:

                 
      keylget args MSGID mh
      keylget args ARGS.DBDIR dbdir
      keylget args ARGS.DBNAME dbname

      set msg [msgget $mh]
      package require sqlite
      set database $dbdir/$dbname
      sqlite3 db $database

      set dbInsertStmt {Insert into msg (data) values ($msg)}
      set result [db eval $dbInsertStmt]

      db close

    Viewing 15 reply threads
    • Author
      Replies
      • #73905

        Here’s an example of how I’ve done it in the past.


        [code]

        -- Max Drown (Infor)

      • #73906
        Ian Morris
        Participant

          Here’s how I do mine.  I do the regsub because a single quote in your message will prevent your message from entering the database properly.  I do the “null” on insert because I have the first field (id) set to auto increment.

          Code:


          regsub -all “‘” $HL7Msg “”” HL7Msg
          package require sqlite
          set dbName “/path/to/database.db”
           sqlite DBCMD $dbName
           set sql “insert into databasename (id,message) values(null,’$HL7Msg’)”
           echo $sql
           DBCMD eval $sql
           DBCMD close

        • #73907
          David Barr
          Participant

            I think it is actually preferable to pass the TCL variable names to SQLite rather than the values. This can avoid problems with quotes and other escape sequences in the data and potentially protect you against SQL injection attacks (although that is pretty unlikely in this case).

            Here’s some documentation I found on the web:

            Quote:

            Tcl variable names can appear in the SQL statement of the second argument in any position where it is legal to put a string or number literal. The value of the variable is substituted for the variable name. If the variable does not exist a NULL values is used. For example:

               db1 eval {INSERT INTO t1 VALUES(5,$bigstring)}

            Note that it is not necessary to quote the $bigstring value. That happens automatically. If $bigstring is a large string or binary object, this technique is not only easier to write, it is also much more efficient since it avoids making a copy of the content of $bigstring.

          • #73908
            Ian Morris
            Participant

              David, are you saying instead of this:

              Code:

              set sql “insert into databasename (id,message) values(null,’$HL7Msg’)”


              do this

              Code:

              set sql “insert into databasename (id,message) values(null,$HL7Msg)”


              ?

              David Barr wrote:

              I think it is actually preferable to pass the TCL variable names to SQLite rather than the values. This can avoid problems with quotes and other escape sequences in the data and potentially protect you against SQL injection attacks (although that is pretty unlikely in this case).

              Here’s some documentation I found on the web:

              Quote:

              Tcl variable names can appear in the SQL statement of the second argument in any position where it is legal to put a string or number literal. The value of the variable is substituted for the variable name. If the variable does not exist a NULL values is used. For example:

            • #73909
              Jerry Tilsley
              Participant

                Thanks all, I did get this to work!

              • #73910
                David Barr
                Participant

                  Ian Morris wrote:

                  David, are you saying instead of this:

                  Code:

                  set sql “insert into databasename (id,message) values(null,’$HL7Msg’)”


                  do this

                  Code:

                  set sql “insert into databasename (id,message) values(null,$HL7Msg)”


                  ?

                  No, you should do this:

                  Code:

                  set sql {insert into databasename (id,message) values(null,$HL7Msg)}

                  And don’t worry about doing a regsub to fix the single quotes. They aren’t a problem if you use this style of programming.

                • #73911
                  Ian Morris
                  Participant

                    Great.  Thanks for the clarification.

                  • #73912
                    Steve Pringle
                    Participant

                      David,

                      When I use the following tcl statment with curly braces

                      set insert {insert into dbo.tumble (id, msg) values ($id, $msg)}

                      I get an error when I execute it:

                      insert = insert into dbo.tumble (id, msg) values ($id, $msg)

                      tumble: Failed to insert msg  [DataDirect][ODBC SQL Server Driver][SQL Server]Invalid pseudocolumn “$id”.

                      stmt_err = SQL_ERROR sql statement = insert into dbo.tumble (id, msg) values ($id, $msg)

                      If I add single quotes around the params it works fine.

                      Here’s a code snippet:

                             set insert {insert into dbo.tumble (id, msg) values ($id, $msg)}

                             if { $debug } { echo “insert = $insert” }

                             set stmt_err [odbc SQLExecDirect $hstmt $insert SQL_NTS]

                             if { $stmt_err != “SQL_SUCCESS” } {

                                 # try to determine why the query failed

                                 catch {odbc SQLGetDiagRec SQL_HANDLE_STMT $hstmt 1

                                     SqlState NativeError errText 511 TextLength}

                                 set errormsg “$procName: Failed to insert msgt

                                     $errText”

                                 if { $debug } {

                                     echo “$errormsgnstmt_err = $stmt_errt sql statement =

                                         $insert”

                                 }

                      Note that this is going against a SQL Server.

                      Any thoughts on why this is failing?

                      thanks,

                      Steve

                    • #73913
                      Charlie Bursell
                      Participant

                        Tcl will not evaluate variables inside of Braces {}

                        Assuming your variables are set, try this:

                        set stmt_err [odbc SQLExecDirect $hstmt [subst $insert] SQL_NTS]

                      • #73914
                        Steve Pringle
                        Participant

                          Charlie,

                          That works, but only where the HL7 msg does not have a single quote in it.  If the msg has a single quote you have to do a regsub on it, as I’m sure you know.  It does’t look like there’s anyway around doing a regsub.

                          I use:    

                          Code:

                          regsub -all {’} $msg “”” msg

                          thanks,

                          Steve

                        • #73915
                          Charlie Bursell
                          Participant

                            set msg [string map

                              $map]

                              Do same for ID if it has apostrephes

                              Note ” aove is two apostrephes not a double quote

                          • #73916
                            Steve Pringle
                            Participant

                              That works!

                              Code:

                              set msg [string map [list ‘ ”] $msg]

                              So I’m guessing ‘string map’ is more efficient than ‘regsub’.

                              thanks,

                              Steve

                            • #73917
                              Charlie Bursell
                              Participant

                                In this case, yes

                              • #73918
                                David Barr
                                Participant

                                  Steve,

                                  The earlier messages in this thread were about SQLite. The way that you bind program variables to database columns is very simple. You’re asking how to do it with DataDirect Connect. For that you need to use SQLBindParameter. There’s an example of how to do this in the Cloverleaf documentation. I think it is something like this:

                                  Code:

                                  set insert “insert into dbo.tumble (id, msg) values (?, ?)”
                                  odbc SQLPrepare $hstmt $insert SQL_NTS
                                  odbc SQLBindParameter $hstmt 1 SQL_PARAM_INPUT
                                   SQL_C_DOUBLE SQL_DOUBLE 0 0 id 0 NULL
                                  odbc SQLBindParameter $hstmt 2 SQL_PARAM_INPUT
                                   SQL_C_CHAR SQL_CHAR 1000 0 msg 50 NULL
                                  odbc SQLExecute $hstmt

                                • #73919
                                  Steve Pringle
                                  Participant

                                    Thanks David,

                                    I know how to bind/fetch the variables, I mistakenly thought you had found a way to pass a string in to SQL w/o having to modify the string based on the presence of single quotes.

                                    –Steve

                                  • #73920
                                    David Barr
                                    Participant

                                      With sqlite, you can pass $variable to the library so you don’t have to worry about quotes. With DataDirect, you can either use SQLBindParameter to avoid the quote problems or escape quotes from your variables as you substitute them into the SQL command on your own.

                                  Viewing 15 reply threads
                                  • The forum ‘Cloverleaf’ is closed to new topics and replies.