Skip to content

Commit

Permalink
Add feature to copy row as SQL
Browse files Browse the repository at this point in the history
  • Loading branch information
Paxa committed Aug 29, 2021
1 parent bfd842a commit de58d71
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 3 deletions.
6 changes: 5 additions & 1 deletion app/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ $u.contextMenu = function (elementArg, options, params) {
var menu = element.contextmenu = new Menu();
for (var n in options) {
if (options[n] && typeof options[n] == 'string') {
menu.append(new MenuItem({ type: options[n] }));
if (options[n] == 'separator') {
menu.append(new MenuItem({ type: options[n] }));
} else {
menu.append(new MenuItem({ role: options[n] }));
}
} else {
menu.append(new MenuItem({ label: n, click: options[n] }));
}
Expand Down
81 changes: 80 additions & 1 deletion app/views/panes/content.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
var Client = require('pg').Client;
var pgEscape = require('pg-escape');

var typesWithoutQuotes = [
'bigint', 'integer', 'real', 'smallint', 'double precision', 'numeric', 'decimal',
'int2vector', 'int4range', 'int8range', 'numrange', 'boolean'
];

var filterMatchers = (() => {
var pgClient = new Client();
Expand Down Expand Up @@ -459,11 +465,27 @@ class Content extends PaneBase {
this.editField(el);
};

contextMenuActions['Copy Row as SQL'] = (menuItem, bwin) => {
var event = table[0].contextmenu.clickEvent;
var el = event.target.tagName == 'TR' ? event.target : $u(event.target).closest('tr')[0];
this.copyRowAsSql(el);
};

contextMenuActions['Add New Row'] = (menuItem, bwin) => {
this.addRow();
};
}
$u.contextMenu(table, contextMenuActions);
$u.contextMenu(table, contextMenuActions, {
// if text is not selected - disable copy button
onShow: (event, contextmenu) => {
var isTextSelected = window.getSelection().toString() != "";
contextmenu.items.forEach(item => {
if (item.label == "Copy") {
item.enabled = isTextSelected;
}
});
}
});

if (this.currentTableType == 'BASE TABLE') {
// for empty area when table is empty
Expand All @@ -490,6 +512,63 @@ class Content extends PaneBase {
}
}

copyRowAsSql (row) {
var ctid = $u(row).attr('data-ctid');
var selectedRow = this.currentData.rows.find(row => {
return row.ctid == ctid;
});

var fieldNames = []
var escapedValues = [];

this.currentData.fields.forEach(field => {
var fieldName = field.name;
if (fieldName != 'ctid') {
fieldNames.push(fieldName);
var escapedValue = '';
var colType = this.columnTypes[fieldName].data_type;
var escapedValue = this.valueToSqlInsert(selectedRow[fieldName], colType);
escapedValues.push(escapedValue);
}
})
var joinedFields = fieldNames.map(f => '"' + f + '"').join(", ");
var joinedValues = escapedValues.join(", ");
var sql = `INSERT INTO "${this.handler.currentSchema}"."${this.handler.currentTable}" (${joinedFields}) VALUES (${joinedValues})`;
console.log("Insert SQL", sql);
electron.clipboard.writeText(sql);
}

valueToSqlInsert(value, colType, insideArray) {
if (value === null) {
return 'NULL';
}
var isArray = colType.endsWith("[]") || Array.isArray(value);
if (isArray) {
var arrayElements = value.map(elementVal => {
return this.valueToSqlInsert(elementVal, colType.replace(/\[\]$/, ''), true);
})
if (insideArray) {
return `[${arrayElements.join(", ")}]`;
} else {
return `ARRAY [${arrayElements.join(", ")}]`;
}
} else if (typesWithoutQuotes.includes(colType)) {
return value;
} else if (colType == 'json' || colType == 'jsonb') {
if (insideArray) {
return `'${pgEscape.string(JSON.stringify(value))}'::${colType}`;
} else {
return `'${pgEscape.string(JSON.stringify(value))}'`;
}
} else {
if (typeof value == 'string') {
return pgEscape('%L', value)
} else {
return `'${pgEscape.string(value)}'`;
}
}
}

async editField (field) {
var position = $u(field).prevAll('td').length;
var ctid = $u(field).closest('tr').attr('data-ctid');
Expand Down
3 changes: 2 additions & 1 deletion vendor/datasets/different_types.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ CREATE TABLE different_types (
col_array_int integer[],
col_matrix_3x3 integer[3][3],
col_array_text text[],
song text[][],
col_hstore hstore,
col_gender human_gender
col_gender human_gender,
);

-- insert all nulls
Expand Down
104 changes: 104 additions & 0 deletions views/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -2916,6 +2916,110 @@ pug_html = pug_html + "\n \u003Ctable\u003E\u003C\u002Ftable\u003E\n \u0
;pug_debug_line = 16;pug_debug_filename = "views\u002Fquery_tab.jade";
pug_html = pug_html + "\n \u003Cdiv class=\"status\"\u003E\u003C\u002Fdiv\u003E\n\u003C\u002Fdiv\u003E";} catch (err) {pug.rethrow(err, pug_debug_filename, pug_debug_line, pug_debug_sources[pug_debug_filename]);};return pug_html;};
exports["query_tab"].content = ".editing\n textarea.editor\n.middlebar\n .resizer\n button.native-look(exec=\"runQuery\" title=\"Cmd+R\") Run Query\n button.native-look(exec=\"showHistory\") See History\n button.native-look(exec=\"openSnippets\") Snippets\n button.native-look(exec=\"saveSnippet\" title=\"Cmd+S\") Save Snippet\n button.native-look.is-hidden.cleanButton(exec=\"cleanButtonClick\" title=\"Clear results bellow\") Clear\n button.native-look.is-hidden.saveButton(exec=\"saveQueryResult\" title=\"Save Result as CSV file\") Save as CSV\n.result\n .rescol-wrapper\n .rescol-header-wrapper\n .rescol-content-wrapper\n table\n .status";
exports["sequnece_structure_tab"] = function template(pug, locals) {var pug_html = "", pug_mixins = {}, pug_interp;var pug_debug_filename, pug_debug_line;try {var pug_debug_sources = {"views\u002Fsequnece_structure_tab.jade":"h4 Sequence\n\ntable.object-details-table\n tr\n td Data Type:\n td= sequence.data_type\n tr\n td Current Value:\n td= sequence.start_value\n tr\n td Minimum:\n td= sequence.minimum_value\n tr\n td Maximum:\n td= sequence.maximum_value\n tr\n td Increment By:\n td= sequence.increment\n tr\n td Cycle:\n td= sequence.cycle_option\n if sequence.dep_table\n tr\n td Owned By Column:\n td= `${sequence.dep_table}.${sequence.dep_column}`\n if sequence.dep_def_value && `${sequence.dep_def_value}`.includes(sequence.sequence_name)\n tr\n td Owner Default Value:\n td= sequence.dep_def_value\n"};
;
var locals_for_with = (locals || {});

(function (sequence) {
var pug_indent = [];
;pug_debug_line = 1;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n\u003Ch4\u003E";
;pug_debug_line = 1;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Sequence\u003C\u002Fh4\u003E";
;pug_debug_line = 3;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n\u003Ctable class=\"object-details-table\"\u003E";
;pug_debug_line = 4;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 5;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 5;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Data Type:\u003C\u002Ftd\u003E";
;pug_debug_line = 6;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 6;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.data_type) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 7;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 8;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 8;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Current Value:\u003C\u002Ftd\u003E";
;pug_debug_line = 9;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 9;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.start_value) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 10;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 11;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 11;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Minimum:\u003C\u002Ftd\u003E";
;pug_debug_line = 12;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 12;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.minimum_value) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 13;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 14;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 14;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Maximum:\u003C\u002Ftd\u003E";
;pug_debug_line = 15;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 15;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.maximum_value) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 16;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 17;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 17;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Increment By:\u003C\u002Ftd\u003E";
;pug_debug_line = 18;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 18;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.increment) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 19;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 20;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 20;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Cycle:\u003C\u002Ftd\u003E";
;pug_debug_line = 21;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 21;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.cycle_option) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
;pug_debug_line = 22;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
if (sequence.dep_table) {
;pug_debug_line = 23;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 24;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 24;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Owned By Column:\u003C\u002Ftd\u003E";
;pug_debug_line = 25;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 25;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = `${sequence.dep_table}.${sequence.dep_column}`) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
}
;pug_debug_line = 26;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
if (sequence.dep_def_value && `${sequence.dep_def_value}`.includes(sequence.sequence_name)) {
;pug_debug_line = 27;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctr\u003E";
;pug_debug_line = 28;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 28;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "Owner Default Value:\u003C\u002Ftd\u003E";
;pug_debug_line = 29;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + "\n \u003Ctd\u003E";
;pug_debug_line = 29;pug_debug_filename = "views\u002Fsequnece_structure_tab.jade";
pug_html = pug_html + (pug.escape(null == (pug_interp = sequence.dep_def_value) ? "" : pug_interp)) + "\u003C\u002Ftd\u003E\n \u003C\u002Ftr\u003E";
}
pug_html = pug_html + "\n\u003C\u002Ftable\u003E";
}.call(this, "sequence" in locals_for_with ?
locals_for_with.sequence :
typeof sequence !== 'undefined' ? sequence : undefined));
;} catch (err) {pug.rethrow(err, pug_debug_filename, pug_debug_line, pug_debug_sources[pug_debug_filename]);};return pug_html;};
exports["sequnece_structure_tab"].content = "h4 Sequence\n\ntable.object-details-table\n tr\n td Data Type:\n td= sequence.data_type\n tr\n td Current Value:\n td= sequence.start_value\n tr\n td Minimum:\n td= sequence.minimum_value\n tr\n td Maximum:\n td= sequence.maximum_value\n tr\n td Increment By:\n td= sequence.increment\n tr\n td Cycle:\n td= sequence.cycle_option\n if sequence.dep_table\n tr\n td Owned By Column:\n td= `${sequence.dep_table}.${sequence.dep_column}`\n if sequence.dep_def_value && `${sequence.dep_def_value}`.includes(sequence.sequence_name)\n tr\n td Owner Default Value:\n td= sequence.dep_def_value\n";
exports["snippet_preview"] = function template(pug, locals) {var pug_html = "", pug_mixins = {}, pug_interp;var pug_debug_filename, pug_debug_line;try {var pug_debug_sources = {"views\u002Fsnippet_preview.jade":".preview-content\n p= snippet.description\n\n code.result.pgsql= snippet.sql\n\n button(exec=\"insert\") Insert to Editor\n"};
;
var locals_for_with = (locals || {});
Expand Down

0 comments on commit de58d71

Please sign in to comment.