From 0694d7f8d2de2ceb62dc6a7320f1d624e5547191 Mon Sep 17 00:00:00 2001 From: Pavel Date: Sun, 23 Mar 2014 01:31:39 +0700 Subject: [PATCH] Implement simple table model, add short style initialiser to class constructor "a = klass(1);" instead "a = new klass(1);" --- app/connection.js | 48 ++------------------------- app/db_screen.js | 12 +++---- app/models/base.js | 22 ++++++++++++- app/models/table.js | 59 ++++++++++++++++++++++++++++++++++ app/views/dialogs/new_table.js | 2 +- build.sh | 2 +- index.js | 3 ++ lib/jquery.class.js | 13 ++++++++ 8 files changed, 106 insertions(+), 55 deletions(-) create mode 100644 app/models/table.js diff --git a/app/connection.js b/app/connection.js index 440274b3..f03a5385 100644 --- a/app/connection.js +++ b/app/connection.js @@ -49,6 +49,7 @@ global.Connection = jClass.extend({ historyRecord.time = Date.now() - time; if (error) { historyRecord.error = error; + console.error("SQL failed", sql); console.error(error); if (callback) callback(result, error); } else { @@ -126,38 +127,6 @@ global.Connection = jClass.extend({ }) }, - tableStructure: function(schema, table, callback) { - var sql = "select * from information_schema.columns where table_schema = '%s' and table_name = '%s';" - this.q(sql, schema, table, function(data) { - this.getPrimaryKey(schema, table, function(rows, error) { - if (!error) { - var keys = rows.map(function(r) { - return r.attname; - }); - - data.rows.forEach(function(row) { - row.is_primary_key = keys.indexOf(row.column_name) != -1; - }); - } - callback(data); - }); - }.bind(this)); - }, - - getPrimaryKey: function (schema, table, callback) { - var sql = "SELECT pg_attribute.attname \ - FROM pg_index, pg_class, pg_attribute \ - WHERE \ - pg_class.oid = '%s'::regclass AND \ - indrelid = pg_class.oid AND \ - pg_attribute.attrelid = pg_class.oid AND \ - pg_attribute.attnum = any(pg_index.indkey) \ - AND indisprimary;"; - this.q(sql, table, function(data, error) { - callback((data || {}).rows, error); - }); - }, - getExtensions: function(callback) { // 'select * from pg_available_extensions order by (installed_version is null), name;' this.q('select * from pg_available_extensions order by name;', function(data) { @@ -221,20 +190,7 @@ global.Connection = jClass.extend({ if (encoding) sql += " ENCODING '" + encoding + "'"; if (template) sql += " TEMPLATE " + template; this.q(sql, dbname, callback); - }, - - createTable: function (tableName, schema, callback) { - sql = "CREATE TABLE %s (id SERIAL PRIMARY KEY)"; - if (schema != '' && schema != 'public') { - sql += sprintf(" TABLESPACE %s", schema); - } - - this.q(sql, tableName, callback); - }, - - dropTable: function (schema, table, callback) { - this.q("DROP TABLE %s", table, callback); - }, + } }); global.Connection.instances = []; \ No newline at end of file diff --git a/app/db_screen.js b/app/db_screen.js index 459cc0b5..a58154b6 100644 --- a/app/db_screen.js +++ b/app/db_screen.js @@ -62,8 +62,8 @@ global.DbScreen = jClass.extend({ }, fetchTableStructure: function(schema, table, callback) { - this.connection.tableStructure(schema, table, function (data) { - callback(data.rows); + Model.Table(schema, table).getStructure(function (data) { + callback(data); }.bind(this)); }, @@ -89,9 +89,9 @@ global.DbScreen = jClass.extend({ contentTabActivate: function() { this.connection.getTableContent(this.currentSchema, this.currentTable, function(data) { - this.connection.tableStructure(this.currentSchema, this.currentTable, function (sdata) { + Model.Table(this.currentSchema, this.currentTable).getStructure(function (sdata) { data.fields.forEach(function(feild) { - sdata.rows.forEach(function(r) { + sdata.forEach(function(r) { if (r.column_name == feild.name) feild.real_format = r.udt_name; }); }); @@ -146,7 +146,7 @@ global.DbScreen = jClass.extend({ }, createTable: function (data, callback) { - this.connection.createTable(data.name, data.tablespace, function (res, error) { + Model.Table.create(data.name, data.tablespace, function (res, error) { if (!error) { this.omit('table.created'); this.fetchTablesAndSchemas(function(tables) { @@ -160,7 +160,7 @@ global.DbScreen = jClass.extend({ }, dropTable: function (schema, table, callback) { - this.connection.dropTable(schema, table, function (res, error) { + Model.Table(schema, table).remove(function (res, error) { this.omit('table.deleted'); this.fetchTablesAndSchemas(); callback && callback(res, error); diff --git a/app/models/base.js b/app/models/base.js index 5d03c5b0..6363cdf3 100644 --- a/app/models/base.js +++ b/app/models/base.js @@ -3,5 +3,25 @@ global.Model = {}; global.Model.base = jClass.extend({ init: function(data) { this.data = data; + }, + + q: function () { + if (App.currentTab.instance.connection) { + return Connection.prototype.q.apply(App.currentTab.instance.connection, arguments); + } else { + throw "Current tab is not connected yet"; + } + }, + + connection: function () { + return Model.base.connection(); + } +}); + +Model.base.connection = function() { + if (App.currentTab.instance.connection) { + return App.currentTab.instance.connection; + } else { + throw "Current tab is not connected yet"; } -}); \ No newline at end of file +}; \ No newline at end of file diff --git a/app/models/table.js b/app/models/table.js new file mode 100644 index 00000000..5294dd99 --- /dev/null +++ b/app/models/table.js @@ -0,0 +1,59 @@ +global.Model.Table = Model.base.extend({ + init: function (schema, table_name) { + this.schema = schema; + this.table = table_name; + }, + + rename: function (new_name, callback) { + + }, + + remove: function(callback) { + this.q("DROP TABLE %s", this.table, callback); + }, + + getStructure: function (callback) { + var sql = "select * from information_schema.columns where table_schema = '%s' and table_name = '%s';" + this.q(sql, this.schema, this.table, function(data) { + this.getPrimaryKey(function(rows, error) { + if (!error) { + var keys = rows.map(function(r) { + return r.attname; + }); + + data.rows.forEach(function(row) { + row.is_primary_key = keys.indexOf(row.column_name) != -1; + }); + } + callback(data.rows); + }); + }.bind(this)); + }, + + getPrimaryKey: function (callback) { + var sql = "SELECT pg_attribute.attname \ + FROM pg_index, pg_class, pg_attribute \ + WHERE \ + pg_class.oid = '%s'::regclass AND \ + indrelid = pg_class.oid AND \ + pg_attribute.attrelid = pg_class.oid AND \ + pg_attribute.attnum = any(pg_index.indkey) \ + AND indisprimary;"; + this.q(sql, this.table, function(data, error) { + callback((data || {}).rows, error); + }); + } +}); + +Model.Table.create = function (tableName, schema, callback) { + sql = "CREATE TABLE %s (id SERIAL PRIMARY KEY)"; + if (schema != '' && schema != 'public') { + sql += sprintf(" TABLESPACE %s", schema); + } + + Model.base.connection().q(sql, tableName, callback); +}; + +Model.Table.l = function (schema, table_name) { + return new Model.Table(schema, table_name); +}; \ No newline at end of file diff --git a/app/views/dialogs/new_table.js b/app/views/dialogs/new_table.js index 463f90e2..d73ee6ec 100644 --- a/app/views/dialogs/new_table.js +++ b/app/views/dialogs/new_table.js @@ -8,7 +8,7 @@ global.Dialog.NewTable = global.Dialog.extend({ showWindow: function () { this.handler.connection.tableSchemas(function(schemas) { - console.log(schemas); + //console.log(schemas); var nodes = App.renderView('dialogs/new_table'); this.content = this.renderWindow(this.title, nodes); diff --git a/build.sh b/build.sh index 18eeeb36..a0bfd7ca 100755 --- a/build.sh +++ b/build.sh @@ -23,11 +23,11 @@ fi #cp -r . ~/postbird.app/Contents/Resources/app.nw rm ${APP_TARGET_DIR}/build.sh + rm ${APP_TARGET_DIR}/run rm ${APP_TARGET_DIR}/pg.icns rm ${APP_TARGET_DIR}/pg.png rm ${APP_TARGET_DIR}/info.plist rm -rf ${APP_TARGET_DIR}/notifier.app - # copy icon and plist file cp ./pg.icns ${TARGET_DIR}/Contents/Resources diff --git a/index.js b/index.js index d7b6c9b9..4c9a73bd 100644 --- a/index.js +++ b/index.js @@ -20,6 +20,9 @@ require('./app/views/dialogs/new_table'); require('./app/views/dialogs/edit_user'); require('./app/views/dialogs/new_database'); +require('./app/models/base'); +require('./app/models/table'); + require('./app/notificator'); //var anyDB = require('any-db'); diff --git a/lib/jquery.class.js b/lib/jquery.class.js index c826bd69..efc431bc 100644 --- a/lib/jquery.class.js +++ b/lib/jquery.class.js @@ -4,6 +4,13 @@ */ // Inspired by base2 and Prototype (function(){ + var newCall = function (Cls, args) { + var constructorArgs = [Cls].concat(Array.prototype.slice.call(args)); + // Cls.bind(Cls, args[0], args[1], args[2], ..) # Cls.bind(Cls, *args) + // Cls.bind.apply(Cls, [Cls] + args); + return new (Function.prototype.bind.apply(Cls, constructorArgs)); + }; + var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The base jClass implementation (does nothing) this.jClass = function(){}; @@ -44,6 +51,12 @@ // The dummy jClass constructor function jClass() { + // when we do direct call of class. eg. + // (new MyClass('name')).doSomethimg => MyClass('name').doSomethimg + if (!(this instanceof jClass)) { + return newCall(jClass, arguments); + } + // All construction is actually done in the init method if ( !initializing && this.init ) this.init.apply(this, arguments);