1

Can someone explain how the rowsx variable is getting overwritten when passed into the generateBulkInsertQueries function? I expect the length value of rowsx to be 1 throughout the entire piece of code

//HELPER FUNCTIONS-------------------------------------------
var generateBulkInsertQueries = (
    data,
    dbname,
    tablename,
    colnames,
    batchSize=10
  ) => {
    if ([dbname, tablename].some((element) => element.indexOf('..') > -1))
      throw `generateInsertQueries() expected distinct db (${dbname}) and tables (${tablename})`;
    //if the colnames param is passed use it, otherwise generate colnames form the data
    if (!dbname || dbname.length < 1) throw `generateInsertQueries(): invalid dbname (${dbname})`;
    let cols = colnames ? colnames : Object.keys(data[0]); //transform keys are column names
    //transform values are inserted strings
    let values = [];
    for(let rows of splitArrayIntoChunks(data,batchSize))
    {
      let ss=rows.map(r=>`(${sqlConcatOneLine(r,cols)})`)
      values.push({outdata:`insert into [${dbname}].[dbo].[${tablename}](${cols.map((c) => `[${c}]`).join(',')}) values ${ss.join(',')}`,indata:rows});
    };
    return values
  };
  
  //demo:   let  [list,chunkSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6];
  //https://stackoverflow.com/questions/8495687/split-array-into-chunks
  var splitArrayIntoChunks=(list,chunkSize)=>{
  list = [...Array(Math.ceil(list.length / chunkSize))].map(_ => list.splice(0,chunkSize))
  //console.log(list);
  return list
  }
  
  var sqlConcatOneLine=(row,cols)=>{
    return cols
          .map((k) => {
            let ret = "''";
            try {
              ret = "'" + row[k].toString().replace(/'/g, '').replace(/\n/g, '').replace(/\r/g, '').toString() + "'";
            } catch (e) {
              // console.log(
              //   `WARN: err inserting value (likely null) generateSQLBulkInsertQuery: ${e}`
              // );
            }
            return ret;
          })
          .join(',')
  }

//EXAMPLE OF ERROR STARTS HERE--------------------------------
(async ()=>{

//init the var
var rowsx = [{ col1: "1", col2: "2" }];
console.log({rowsxlen:rowsx.length,here:1})
var sqliq = generateBulkInsertQueries(rowsx, 'xx', 'yy', ['col1','col2'],1);

console.log({rowsxlen:rowsx.length,here:2})
if(rowsx.length!=1) console.log(`failed. rowsx.length!=1`)
else console.log(`success!!!!`)
})()
Rilcon42
  • 9,584
  • 18
  • 83
  • 167

1 Answers1

2

You've got a splice() (doc) applied to the first param of splitArrayIntoChunks, which is the data param of the containing function, which is the rowsx array you're hoping not to mutate.

So the approach to chunking used here mutates its input. Either do it with a non-destructive reduce (see here, from the same article you used), or make a copy the input over which to apply the splice. (Demo'd that below)

//HELPER FUNCTIONS-------------------------------------------
var generateBulkInsertQueries = (
    data,
    dbname,
    tablename,
    colnames,
    batchSize=10
  ) => {
    if ([dbname, tablename].some((element) => element.indexOf('..') > -1))
      throw `generateInsertQueries() expected distinct db (${dbname}) and tables (${tablename})`;
    //if the colnames param is passed use it, otherwise generate colnames form the data
    if (!dbname || dbname.length < 1) throw `generateInsertQueries(): invalid dbname (${dbname})`;
    let cols = colnames ? colnames : Object.keys(data[0]); //transform keys are column names
    //transform values are inserted strings
    let values = [];
    for(let rows of splitArrayIntoChunks(data,batchSize))
    {
      let ss=rows.map(r=>`(${sqlConcatOneLine(r,cols)})`)
      values.push({outdata:`insert into [${dbname}].[dbo].[${tablename}](${cols.map((c) => `[${c}]`).join(',')}) values ${ss.join(',')}`,indata:rows});
    };
    return values
  };
  
  //demo:   let  [list,chunkSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6];
  //https://stackoverflow.com/questions/8495687/split-array-into-chunks
  var splitArrayIntoChunks=(list,chunkSize)=>{
    let spliceMe = [...list];
    return [...Array(Math.ceil(list.length / chunkSize))].map(_ => spliceMe.splice(0,chunkSize))
    //console.log(list);
  }
  
  var sqlConcatOneLine=(row,cols)=>{
    return cols
          .map((k) => {
            let ret = "''";
            try {
              ret = "'" + row[k].toString().replace(/'/g, '').replace(/\n/g, '').replace(/\r/g, '').toString() + "'";
            } catch (e) {
              // console.log(
              //   `WARN: err inserting value (likely null) generateSQLBulkInsertQuery: ${e}`
              // );
            }
            return ret;
          })
          .join(',')
  }

//EXAMPLE OF ERROR STARTS HERE--------------------------------
(async ()=>{

//init the var
var rowsx = [{ col1: "1", col2: "2" }];
console.log({rowsxlen:rowsx.length,here:1})
var sqliq = generateBulkInsertQueries(rowsx, 'xx', 'yy', ['col1','col2'],1);

console.log({rowsxlen:rowsx.length,here:2})
if(rowsx.length!=1) console.log(`failed. rowsx.length!=1`)
else console.log(`success!!!!`)
})()
danh
  • 62,181
  • 10
  • 95
  • 136