diff options
author | jakefeasel <jfeasel@gmail.com> | 2012-09-26 23:57:14 -0700 |
---|---|---|
committer | jakefeasel <jfeasel@gmail.com> | 2012-09-26 23:57:14 -0700 |
commit | 6abd62b926bf4425a25e050eec4d521c3104ba36 (patch) | |
tree | c10fd5f34d315bee936dfb6bfed09602ee2b56cf /javascripts/libs/ddl_builder/ddl_builder.js | |
parent | c7f479246e9c2c02e9ef255061ad3fe6462243c6 (diff) | |
download | sqlfiddle-6abd62b926bf4425a25e050eec4d521c3104ba36.zip sqlfiddle-6abd62b926bf4425a25e050eec4d521c3104ba36.tar.gz sqlfiddle-6abd62b926bf4425a25e050eec4d521c3104ba36.tar.bz2 |
Pulling out the QUnit tests into AMD modules
Diffstat (limited to 'javascripts/libs/ddl_builder/ddl_builder.js')
-rw-r--r-- | javascripts/libs/ddl_builder/ddl_builder.js | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/javascripts/libs/ddl_builder/ddl_builder.js b/javascripts/libs/ddl_builder/ddl_builder.js new file mode 100644 index 0000000..43b363d --- /dev/null +++ b/javascripts/libs/ddl_builder/ddl_builder.js @@ -0,0 +1,382 @@ +define( + [ + "jQuery", + "Handlebars", + "DateFormat", + 'HandlebarsHelpers/each_with_index' + ], + function ($, Handlebars, dateFormat) { + + ddl_builder = function (args) { + if (!args) args = {}; + // output settings + this.fieldPrefix = ''; + this.fieldSuffix = ''; + this.tablePrefix = ''; + this.tableSuffix = ''; + + + this.dateFormatMask = "yyyy-mm-dd HH:MM:ss"; + + this.charType = 'varchar'; + this.intType = 'int'; + this.floatType = 'numeric'; + this.dateType = 'datetime'; + + // input settings + this.valueSeparator = ''; + + this.column_count = 0; + this.definition = { + tableName: "Table1", + columns: [/* sample column structure + { + name: 'id', + type: 'int', + length: '', + db_type: 'int4' + }, + { + name: 'name', + type: 'char', + length: 20, + db_type: 'varchar(20)' + } + */], + data: [/* sample data structure + // r for "row", v for "value" + {r:[{v:1},{v:'Jake'}]}, + {r:[{v:2},{v:'Rachel'}]}, + {r:[{v:3},{v:'Andrew'}]}, + {r:[{v:4},{v:'Ada'}]}, + {r:[{v:5},{v:'Lucy O\'Malley'}]} + + + */] + }; + + + this.ddlTemplate = "\ +CREATE TABLE {{{tablePrefix}}}{{tableName}}{{{tableSuffix}}}\n\ + ({{#each_with_index columns}}{{#if index}}, {{/if}}{{{../fieldPrefix}}}{{name}}{{{../fieldSuffix}}} {{db_type}}{{/each_with_index}})\n{{separator}}\n\n\ +INSERT INTO {{{tablePrefix}}}{{tableName}}{{{tableSuffix}}}\n\ + ({{#each_with_index columns}}{{#if index}}, {{/if}}{{{../fieldPrefix}}}{{name}}{{{../fieldSuffix}}}{{/each_with_index}})\n\ +VALUES\n\ + {{#each_with_index data}}{{#if index}},\n\ + {{/if}}({{#each_with_index r}}{{#if index}}, {{/if}}{{formatted_field ../..}}{{/each_with_index}}){{/each_with_index}}\n{{separator}}"; + + this.compiledTemplate = Handlebars.compile(this.ddlTemplate); + this.setup(args); + return this; + } + + ddl_builder.prototype.setup = function (settings) { + for (opt in settings) + { + this[opt] = settings[opt]; + } + + if (settings["ddlTemplate"]) + this.compiledTemplate = Handlebars.compile(this.ddlTemplate); + + if (settings["tableName"]) + this.definition.tableName = settings.tableName; + + return this; + } + + ddl_builder.prototype.setupForDBType = function (type,separator) { + + switch (type) + { + case 'SQL Server': + this.setup({ + statement_separator: separator, + fieldPrefix: '[', + fieldSuffix: ']', + tablePrefix: '[', + tableSuffix: ']' + }); + break; + + case 'MySQL': + this.setup({ + statement_separator: separator, + fieldPrefix: '`', + fieldSuffix: '`', + tablePrefix: '`', + tableSuffix: '`' + }); + break; + case 'PostgreSQL': + this.setup({ + statement_separator: separator, + fieldPrefix: '"', + fieldSuffix: '"' + }); + break; + + case 'Oracle': + var template = +"CREATE TABLE {{{tablePrefix}}}{{tableName}}{{{tableSuffix}}}\n\ + ({{#each_with_index columns}}{{#if index}}, {{/if}}{{{../fieldPrefix}}}{{name}}{{{../fieldSuffix}}} {{db_type}}{{/each_with_index}})\n{{separator}}\n\ +INSERT ALL\ +{{#each_with_index data}}\n\ + INTO \ +{{{../tablePrefix}}}{{../tableName}}{{{../tableSuffix}}} \ +({{#each_with_index r}}{{#if index}}, {{/if}}{{{../../fieldPrefix}}}{{column_name_for_index ../..}}{{{../../fieldSuffix}}}{{/each_with_index}})\n\ + VALUES \ +({{#each_with_index r}}{{#if index}}, {{/if}}{{formatted_field ../..}}{{/each_with_index}})\ +{{/each_with_index}}\n\ +SELECT * FROM dual\n{{separator}}"; + + this.setup({ + + statement_separator: separator, + ddlTemplate: template, + dateType: 'timestamp', + charType: 'varchar2', + fieldPrefix: '"', + fieldSuffix: '"' + }); + break; + + + + case 'SQLite': + var template = +"CREATE TABLE {{tablePrefix}}{{tableName}}{{tableSuffix}}\n\ + ({{#each_with_index columns}}{{#if index}}, {{/if}}{{{../fieldPrefix}}}{{name}}{{{../fieldSuffix}}} {{db_type}}{{/each_with_index}})\n{{separator}}\n\n\ +{{#each_with_index data}}\ +INSERT INTO {{tablePrefix}}{{../tableName}}{{tableSuffix}}\n\ + ({{#each_with_index ../columns}}{{#if index}}, {{/if}}{{{../../fieldPrefix}}}{{name}}{{{../../fieldSuffix}}}{{/each_with_index}})\n\ +VALUES\n\ + ({{#each_with_index r}}{{#if index}}, {{/if}}{{formatted_field ../..}}{{/each_with_index}})\n{{../separator}}\ +\n\ +{{/each_with_index}}\ +"; + + + this.setup({ + fieldPrefix: '"', + fieldSuffix: '"', + tablePrefix: '"', + tableSuffix: '"', + statement_separator: separator, + ddlTemplate: template, + dateType: 'DATE', + charType: 'TEXT', + intType: 'INTEGER', + floatType: 'REAL' + }); + break; + + + } + return this; + } + + ddl_builder.prototype.populateDBTypes = function () { + for (var i=0;i<this.definition.columns.length;i++) + { + if (this.definition.columns[i].type == 'charType') + this.definition.columns[i].db_type = this[this.definition.columns[i].type] + "(" + this.definition.columns[i].length + ")"; + else + this.definition.columns[i].db_type = this[this.definition.columns[i].type]; + } + + this.definition.dateFormatMask = this.dateFormatMask; + + }; + + ddl_builder.prototype.populateWrappers = function () { + this.definition.fieldPrefix = this.fieldPrefix; + this.definition.fieldSuffix = this.fieldSuffix; + }; + + + ddl_builder.prototype.guessValueSeparator = function (raw) { + + + var lines = raw.split("\n"); + var header_found = false, column_count = 0, found_separator = ''; + + for (var i = 0; i<lines.length; i++) + { + if (lines[i].search(/[A-Z0-9_]/i) != -1 && !header_found) // if this line contains letters/numbers/underscores, then we can assume we've hit the header row + { + var chunks = $.trim(lines[i]).match(/([A-Z0-9_]+ ?)+([^A-Z0-9_]*)/gi); + + header_found = true; + + for (var j = 0; j < chunks.length; j++) + { + var this_separator = chunks[j].match(/[A-Z0-9_]+([^A-Z0-9_]*)$/i).pop(); // gets the last returned value from regexp + + if (this_separator.search(/^\s\s+$/) != -1) + this_separator = new RegExp("\\s\\s+"); + else if (this_separator.search(/^\t+$/) != -1) + this_separator = new RegExp("\\t+"); + else if (this_separator.search(/^\s+$/) != -1) + this_separator = new RegExp("\\s+"); + else + this_separator = $.trim(this_separator); + + if (this_separator instanceof RegExp || this_separator.length) + { + if (!(found_separator instanceof RegExp) && !found_separator.length) + found_separator = this_separator; + else if (found_separator.toString() != this_separator.toString()) + return {status: false, message: 'Unable to find consistent column separator in header row'}; // different separators founds? + } + else if (! (this_separator instanceof RegExp) && !(found_separator instanceof RegExp) && !found_separator.length) + { + found_separator = "\n"; + } + + } + if (found_separator instanceof RegExp || found_separator.length) + column_count = $.trim(lines[i]).split(found_separator).length; + else + column_count = 1; + + + } + else if (lines[i].search(/[A-Z0-9_]/i) != -1) + { + if ($.trim(lines[i]).split(found_separator).length != column_count) + return {status: false, message: 'Line ' + i + ' does not have the same number of columns as the header, based on separator "' + found_separator + '".'}; + + } + + } + return {status: true, separator: found_separator, column_count: column_count}; + } + + ddl_builder.prototype.parse = function (raw) { + + + + if (!this.valueSeparator.length) + { + var result = this.guessValueSeparator(raw); + if (!result.status) + return "ERROR! " + result.message; + else + { + this.column_count = result.column_count; + this.valueSeparator = result.separator; + } + } + + var lines = raw.split("\n"); + + for (var i=0;i<lines.length;i++) + { + if ($.trim(lines[i]).length && $.trim(lines[i]).split(this.valueSeparator).length == this.column_count) + { + + var elements = $.trim(lines[i]).split(this.valueSeparator); + + + if (! this.definition.columns.length) + { + for (var j = 0; j < elements.length; j++) + { + var value = $.trim(elements[j]); + if (value.length) + this.definition.columns.push({"name": value}); + else + this.definition.columns.push(false); + } + } + else + { + + var tmpRow = []; + for (var j = 0; j < elements.length; j++) + { + if (this.definition.columns[j] !== false) + { + var value = $.trim(elements[j]).replace(/'/g, "''"); + + // if the current field is not a number, or if we have previously decided that this one of the non-numeric field types... + if (isNaN(value) || this.definition.columns[j].type == 'dateType' || this.definition.columns[j].type == 'charType') + { + + // if we haven't previously decided that this is a character field, and it can be cast as a date, then declare it a date + if (this.definition.columns[j].type != 'charType' && !isNaN(Date.parse(value)) ) + this.definition.columns[j].type = "dateType"; + else + this.definition.columns[j].type = "charType"; + } + else // this must be some kind of number field + { + if (this.definition.columns[j].type != 'floatType' && value % 1 != 0) + this.definition.columns[j].type = 'floatType'; + else + this.definition.columns[j].type = 'intType'; + } + + if (!this.definition.columns[j].length || value.length > this.definition.columns[j].length) + { + this.definition.columns[j].length = value.length; + } + + tmpRow.push({v:value}); + } + + } + this.definition.data.push({r: tmpRow}); + + } + + } + } + this.populateDBTypes(); + this.populateWrappers(); + return this.render(); + } + + /* HandlebarsJS-using code below */ + + Handlebars.registerHelper("formatted_field", function(root) { + + var colType = ''; + var index = -1; + for (var j = 0; j < root.columns.length; j++) + { + if (root.columns[j]) + index++; + + if (index == this.index) + { + colType = root.columns[j].type; + break; + } + } + + + if (!this.v.length || this.v.toUpperCase() == 'NULL') + return 'NULL'; + if (colType == 'charType') + return new Handlebars.SafeString("'" + this.v.replace(/'/g, "''") + "'"); + + if (colType == 'dateType') + return new Handlebars.SafeString("'" + dateFormat(this.v, root.dateFormatMask) + "'"); + + return this.v; + }); + + Handlebars.registerHelper("column_name_for_index", function(root) { + return root.columns[this.index].name; + }); + + + ddl_builder.prototype.render = function () { + return this.compiledTemplate($.extend(this.definition, {"separator": this.statement_separator})); + } + + return ddl_builder; + +}); |