question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support DELIMITER syntax

See original GitHub issue

Disclaimer: I don’t know a whole lot of SQL

So my dev team decided that we wanted a Node script that could drop and re-create all of our stored procedures whenever something changes. The problem was that this library doesn’t support the delimiter syntax. I made a kind of hacky way to split statements from my .sql (loaded to an in-memory string) file by custom delimiters into an array of separate statements.

Do you guys have a suggested way of working with something like this? How about suggestions for where to start for a PR?

Ex:

DELIMITER $$
DROP PROCEDURE IF EXISTS `Thing_Insert`$$
CREATE PROCEDURE `Thing_Insert`(
	argA int,
	argB nvarchar(50),
	argC nvarchar(50),
	argD datetime,
	argE bit)
BEGIN

	insert into Thing (A, B, C, D, E)
		select argA, argB, argC, argD, argE;

END$$
DELIMITER ;

...etc
/**
 * Separates individual SQL statements, split by a delimiter, into an array of statements
 * @param {String} text
 * @returns {String[]}
 */
function separateSqlCommands(text) {
    let lines = text.split('\n')
        .filter(str => {
            return str.length
                && !/^\n*$/.test(str);
        });

    let delimiter = ';';
    const DELIMITER_REGEX = /DELIMITER (.+)/;

    let statements = [];

    let accumulator = '';

    for(const line of lines) {
        let regexpResult = DELIMITER_REGEX.exec(line);
        if(regexpResult) {
            statements = statements.concat(accumulator.split(delimiter));

            accumulator = '';
            delimiter = regexpResult[1];
        } else {
            accumulator += line + ' ';
        }
    }

    statements = statements.filter(statement => !/^\s*$/.test(statement))
        .map(statement => {
            if(statement[0] === ' ') statement = statement.substr(1);

            return statement.replace(/\t/g, ' ')
                .replace(/ +/g, ' ');
        })
        .map(statement => statement.replace(/ +/g, ' '));

    return statements;
}

example output:

[ 'drop procedure `Thing_Insert`',
  'CREATE PROCEDURE `Thing_Insert`( argA int, argB nvarchar(50), argC nvarchar(50), argD datetime, argE bit) BEGIN insert into Thing (A, B, C, D, E) select argA, argB, argC, argD, argE; END' ]

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:6
  • Comments:17 (3 by maintainers)

github_iconTop GitHub Comments

10reactions
lagdencommented, Nov 28, 2017

@ben-page and @dougwilson

Removing the DELIMITER works!!

const _sql = sql.toString().replace(/DELIMITER ;?;/gm, '').replace(/;;/gm, ';')

Thanks!

8reactions
ben-pagecommented, Dec 1, 2017

I thought I’d clarify a little for anyone coming here looking for DELIMITER support. DELIMITER is a feature of the MySQL CLI, not the MySQL Server. The MySQL CLI interprets queries containing semicolons as multiple statements, splits them, and sends them to the server individually. DELIMITER allows you to control the splitting behavior.

Unfortunately for the OP, mysql doesn’t have this feature. He needs it because he wants to execute .sql files generated for the MySQL CLI with mysql rather than the MySQL CLI.

Fortunately for most people, you probably don’t need DELIMITER support. In most cases you can just run the queries one at a time with multipleStatements set to false. If the query contains a semicolon (such as in a CREATE PROCEDURE statement), it will not cause any problems.

For example if you split the OP’s queries, they run just fine:

'use strict';
const mysql = require('mysql');

const config = {
    host: 'localhost',
    user: 'user',
    password: 'password',
    database: 'database',
    multipleStatements: false //false is the default, added for emphasis
};

const dropQuery = 'DROP PROCEDURE IF EXISTS `Thing_Insert`';
const createQuery = `CREATE PROCEDURE \`Thing_Insert\`(
        argA int,
        argB nvarchar(50),
        argC nvarchar(50),
        argD datetime,
        argE bit)
    BEGIN
    
        insert into Thing (A, B, C, D, E)
            select argA, argB, argC, argD, argE;
    
    END`;

const connection = mysql.createConnection(config);
connection.connect(function(err) {
    if (err) {
        console.error('error connecting: ' + err.stack);
        return;
    }
    
    connection.query(dropQuery, function(err2) {
        if (err2) {
            console.error('error dropping: ' + err2.stack);
            return;
        }
        
        console.log('drop succeeded');
        
        connection.query(createQuery, function(err3) {
            if (err3) {
                console.error('error creating: ' + err3.stack);
                return;
            }
    
            console.log('create succeeded');
            connection.end();
        });
    });
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

MySQL DELIMITER
In this tutorial, you will learn how to change the default MySQL delimiter by using the DELIMITER command.
Read more >
Delimiters - MariaDB Knowledge Base
The solution is to specify a distinct delimiter for the duration of the process, using the DELIMITER command. The delimiter can be any...
Read more >
MySQL 8.0 Reference Manual :: 25.1 Defining Stored Programs
To redefine the mysql delimiter, use the delimiter command. The following example shows how to do this for the dorepeat() procedure just shown....
Read more >
Delimiters in MySQL - Stack Overflow
Delimiters other than the default ; are typically used when defining functions, stored procedures, and triggers wherein you must define ...
Read more >
Syntax for the delimiter form - HCL Informix documentation
The syntax for the delimiter form specifies the field delimiter, the input file, and the number of fields in each row of data....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found