2

I'm trying to run a script where I pull records from one database and then insert the records into another database, but during the insertion step I keep running into this error 8 or 9 repetitions in.

I'm not super familiar with the node-mssql library and would appreciate any insight on what's happening here! I've attached a copy of the stack trace and the script.

  const sql = require('mssql')
        const humENV = require('../env').humENV
        const rbENV = require('../env').rbENV
        const logger = require('./logger')

        const getReviewHumanatic = async () => {
          try {
            let pool = await sql.connect(humENV.SQL_CONFIG)
            let req = await pool.request()
            .query(`
              WITH cte 
              AS (SELECT DISTINCT TOP 500 htaskid, 
                  ht.frn_leuserid, 
                  ht.frn_callid, 
                  ht.frn_hcatid, 
                  ht.frn_hcat_optionid, 
                  frn_lskinid, 
                  cq.duration_seconds, 
                  add_path, 
                  CASE 
                    WHEN call_queueid IS NULL THEN 3 
                    ELSE 1 
                  END AS status, 
                  CASE 
                    WHEN hcab_reviewid IS NULL THEN 0 
                    ELSE 1 
                  END AS HCAB 
                  FROM   htask ht 
                        LEFT JOIN call_queue cq 
                          ON ht.frn_callid = cq.frn_callid 
                        LEFT JOIN hcab_review hr 
                          ON hr.frn_callid = cq.frn_callid 
                            AND ht.frn_leuserid = hr.frn_leuserid) 
              SELECT Isnull(frn_callid, 0)       AS frn_callid,
                    Isnull(frn_hcatid, 0)        AS frn_hcatid, 
                    Isnull(HCAB, 0)              AS HCAB, 
                    Isnull(frn_hcat_optionid, 0) AS frn_hcat_optionid, 
                    Isnull(frn_lskinid, 0)       AS frn_lskinid, 
                    Isnull(frn_leuserid, 0)      AS frn_leuserid, 
                    Isnull(status, 0)            AS status, 
                    Isnull(duration_seconds, 0)  AS duration_seconds, 
                    Isnull(add_path, '')         AS add_path, 
                    Isnull(htaskid, 0)           AS htaskid 
              FROM   cte 
              ORDER BY frn_callid
              `)
            if (req.recordset.length !== 0) {
              console.log(req.recordset)
              logger.info('returning query records')
              return req.recordset
            }
            pool.close()
          } catch (err) {
            logger.error(err)
          }
        }

        const insertRebase = async (data) => {
          try {
            sql.close()
            let pool = await sql.connect(rbENV.SQL_CONFIG)
            for (let i = 0; i < data.length; i++) {
              console.log(data[i])
              let req = await pool.request()
              .input('frn_callid', sql.BigInt, data[i].frn_callid)
              .input('frn_categoryid', sql.Int, data[i].frn_hcatid)
              .input('HCAB', sql.Int, data[i].HCAB)
              .input('frn_answer_optionid', sql.Int, data[i].frn_hcat_optionid)
              .input('frn_leuserid', sql.Int, data[i].frn_leuserid)
              .input('frn_lskinid', sql.Int, data[i].frn_lskinid)
              .input('frn_statusid', sql.TinyInt, data[i].status)
              .input('reviewid', sql.Int, data[i].htaskid)
              .input('call_duration', sql.Int, data[i].duration_seconds)
              .input('HCAB_trigger', sql.VarChar, data[i].add_path)
              .query('SET IDENTITY_INSERT review ON; INSERT INTO review (frn_callid, frn_categoryid, HCAB, frn_answer_optionid, frn_leuserid, frn_lskinid, frn_statusid, reviewid, call_duration, HCAB_trigger) VALUES (@frn_callid, @frn_categoryid, @HCAB, @frn_answer_optionid, @frn_leuserid, @frn_lskinid, @frn_statusid, @reviewid, @call_duration, @HCAB_trigger)', function (err, recordset) {
                if (err) {
                  logger.error(err)
                  console.log(err)
                }
                pool.close()
              })
            }
          } catch (err) {
            logger.error(err)
          }
        }

        const initializeReview = async () => {
          try {
            const humData = await getReviewHumanatic()
            insertRebase(humData)
          } catch (err) {
            console.log(err)
          }
        }

        initializeReview()

I looked at this question NPM MSSQL - error: uncaughtException: Cannot read property 'release' of null but it doesn't look like there was a conclusive solution.

Stack trace of error:

stack trace

EDIT: Since my original post, I've converted the insert query to a preparedstatement:

const insertRebase = async (data) => {
  try {
    sql.close()
    let pool = await sql.connect(rbENV.SQL_CONFIG)
    for (let i = 0; i < data.length; i++) {

      let ps = new sql.PreparedStatement(pool)
      ps.input('frn_callid', sql.BigInt)
      ps.input('frn_categoryid', sql.Int)
      ps.input('HCAB', sql.Int)
      ps.input('frn_answer_optionid', sql.Int)
      ps.input('frn_leuserid', sql.Int)
      ps.input('frn_lskinid', sql.Int)
      ps.input('frn_statusid', sql.TinyInt)
      ps.input('reviewid', sql.Int)
      ps.input('call_duration', sql.Int)
      ps.input('HCAB_trigger', sql.VarChar)
      ps.prepare(`SET IDENTITY_INSERT review ON; INSERT INTO review (frn_callid, frn_categoryid, HCAB, frn_answer_optionid, frn_leuserid, frn_lskinid, frn_statusid, reviewid, call_duration, HCAB_trigger) VALUES (@frn_callid, @frn_categoryid, @HCAB, @frn_answer_optionid, @frn_leuserid, @frn_lskinid, @frn_statusid, @reviewid, @call_duration, @HCAB_trigger)`, err => {
        if (err) {
          console.log(err)
          logger.error(err)
        } else {
          ps.execute({frn_callid: data[i].frn_callid, frn_categoryid: data[i].frn_hcatid, HCAB: data[i].HCAB, frn_answer_optionid: data[i].frn_hcat_optionid, frn_leuserid: data[i].frn_leuserid, frn_lskinid: data[i].frn_lskinid, frn_statusid: data[i].status, reviewid: data[i].htaskid, call_duration: data[i].duration_seconds, HCAB_trigger: data[i].add_path}, (err, result) => {
            if (err) {
              console.log(err)
              logger.error(err)
            } else {
              ps.unprepare(err => {
                if (err) {
                  console.log(err)
                  logger.error(err)
                }
              })
            }
          })
        }
      })
    }
  } catch (err) {
    logger.error(err)
  }
}

I'm unsure as to why a preparedstatement solution works over the previous solution, but the preparedstatement solution doesn't seem to error out and properly inserts all of the records.

As for the sql.close() global connection issue, does doing

const getReviewHumanatic = async () => {
  try {
    let pool1 = await sql.connect(SQL_CONFIG1)
    let req = await pool1.request()
}

create a global connection? I was under the assumption that it was creating a local connection and that if I did

let pool2 = await sql.connect(SQL_CONFIG2)

it would create a separate sql connection, but that doesn't seem to be the case because I can't run the script without doing sql.close() before I can create pool2.

I checked the node-mssql documentation and it looks like if I do a request without a pool specification, it'll use the global sql connection; maybe that's what's happening with my script? https://www.npmjs.com/package/mssql#request

Emily
  • 29
  • 3
  • You said you're inserting from one database to another, did you close connection to first database? Also as @TJ mentioned please use code blocks for stack snippet. – TGW Oct 30 '17 at 09:43
  • @TGW I do close the pool for the first database using `pool.close()` towards the end of the getReviewHumanatic function, and I also do a `sql.close()` at the start of the insertRebase function. I added the `sql.close()` because just doing `pool.close()` would give me an error saying that the global connection already exists and to do a `sql.close()`, but I think I might not be using the sql connections properly because I would imagine `let pool = await sql.connect(humENV.SQL_CONFIG)` wouldn't be a global sql connection. – Emily Oct 30 '17 at 10:10

0 Answers0