michaelbahr
michaelbahr

Reputation: 4963

JavaScript String concat replaces first character

Task

After extracting SQL statements from a log file I'm doing simple string concatenation to append a ; at the end:

var query = line[i] + ";"

Problem

What it should look like: insert into [...];

What it does look like: ;nsert into [...]

Approaches

I tried different concatenation mechanisms, seeing that only appended concatenation fails.

for (i in lines) {
  var txt = lines[i];
  console.log(txt);                 // "insert into"
  console.log(txt.concat(";"));     // ";nsert into"
  console.log(txt + ";");           // ";nsert into"
  console.log(txt+=";");            // ";nsert into"
  console.log(";" + txt);           // ";insert into"
}

Extraction script

var fs = require('fs');
var array = fs.readFileSync('file').toString().split("\n");
var result = [];

var currentRow;
var line;
var value;

// loop through all lines of the file
for(i in array) {
    line = array[i];
    // if there is an insert statement, push it on the array
    if (line.lastIndexOf("insert into", 0) === 0) {
      result.push(line);
    // if there is a binding param, interpolate that into the recent insert statement
    } else if (line.lastIndexOf("binding param", 0) === 0){
      value = line.split(" - ")[1].replace("\n", "").replace("\r", "");
      // hibernate represents null as <null> while oracle needs ""
      if (value === "<null>") {
        value = '""';
      // if there is a string, put "" around
      } else if (isNaN(value)) {
        value = '"' + value + '"';
      }
      currentRow = result[result.length-1];
      // interpolate
      currentRow = currentRow.replace("?", value);
      result[result.length-1] = currentRow;
    }
}

Data sneak peek

insert into <user>.<table> (<col1>, <col2>, <col3>) values (?, ?, ?)
binding parameter [1] as [<type>] - <value>
binding parameter [2] as [<type>] - <value>
binding parameter [3] as [<type>] - <value>

System

Question

Why is the ; not appended but replaces the first character?

Upvotes: 2

Views: 907

Answers (1)

michaelbahr
michaelbahr

Reputation: 4963

As Pointy indicated, there was a terminating carriage return character (ASCII 13 decimal) in the string.

Extending the extraction script to trim the last character if there is one did the trick.

if (line.lastIndexOf("insert into", 0) === 0) {
   if (line.charCodeAt(line.length - 1) == 13) {
     line = line.substring(0, line.length - 1);
   }
   result.push(line);
   console.log(line); // "insert into [...];"
}

Note: There are prettier solutions using regex.

Upvotes: 1

Related Questions