{"id":453,"date":"2013-06-22T17:56:13","date_gmt":"2013-06-22T16:56:13","guid":{"rendered":"http:\/\/www.muratyaman.co.uk\/wp\/?p=453"},"modified":"2020-04-01T12:35:07","modified_gmt":"2020-04-01T11:35:07","slug":"postgresql-and-node-js-100-per-cent-javascript-adventure","status":"publish","type":"post","link":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/2013\/06\/postgresql-and-node-js-100-per-cent-javascript-adventure\/","title":{"rendered":"PostgreSQL and Node.js &#8211; 100% JavaScript Adventure"},"content":{"rendered":"<p>This is a log of every step I will take to create a 100%-JavaScript application back to front.<\/p>\n<p>Hardware: Windows 7 64bit Home Edition ASUS laptop with Intel P6100 CPU @2.0GHz, 4GB RAM, 320GB HDD<\/p>\n<p>Oracle VirtualBox 4.2.12<br \/>\nUbuntu 12.04.2 &#8211; Long term support<br \/>\nDownloaded 32bit ISO image &#8211; laptop does not support 64bit virtualisation \ud83d\ude41<br \/>\nVirtual machine: 1 CPU, 1GB RAM, 20GB HDD, with bridged network, boot CD first to use ISO image<br \/>\nMinimal install with OpenSSH server<\/p>\n<p>Update repositories and upgrade base system<\/p>\n<pre lang=\"bash\">\r\nsudo apt-get update\r\nsudo apt-get upgrade\r\nsudo apt-get install python-software-properties\r\n<\/pre>\n<p>To use PostgreSQL Apt repository, follow: <a href=\"http:\/\/wiki.postgresql.org\/wiki\/Apt\">http:\/\/wiki.postgresql.org\/wiki\/Apt<\/a><\/p>\n<p>Edit source list:<\/p>\n<pre lang=\"bash\">\r\nsudo vim \/etc\/apt\/sources.list\r\n<\/pre>\n<p>and add append this line:<\/p>\n<pre lang=\"bash\">\r\ndeb http:\/\/apt.postgresql.org\/pub\/repos\/apt\/ precise-pgdg main\r\n<\/pre>\n<p>Save and exit.<br \/>\nImport repository key and update.<\/p>\n<pre lang=\"bash\">\r\nwget --quiet -O - http:\/\/apt.postgresql.org\/pub\/repos\/apt\/ACCC4CF8.asc | sudo apt-key add -\r\nsudo apt-get update\r\nsudo apt-get install postgresql-9.2\r\nsudo apt-get install libpq-dev\r\n<\/pre>\n<p>This will also install GCC and many related packages to compile code.<\/p>\n<p>Install Node.js &#8211; refer to <a href=\"http:\/\/nodejs.org\/\">http:\/\/nodejs.org\/<\/a><\/p>\n<pre lang=\"bash\">\r\nsudo apt-get install g++\r\nsudo apt-get install make\r\nsudo add-apt-repository ppa:chris-lea\/node.js\r\nsudo apt-get update\r\nsudo apt-get install nodejs\r\n<\/pre>\n<p>Install git if you want to work with github or bitbucket etc.<\/p>\n<pre lang=\"bash\">\r\nsudo apt-get install git\r\n<\/pre>\n<p>I think my development environment is ready. Next step is to create an application.<\/p>\n<p>Let&#8217;s prepare the database server. Create a database user and a database owned by that user.<\/p>\n<pre lang=\"bash\">\r\nsudo su postgres\r\ncreateuser -P myuser\r\ncreatedb -O myuser mydb\r\n<\/pre>\n<p>Make sure local connections are allowed for local users:<\/p>\n<pre lang=\"bash\">\r\nsudo vim \/etc\/postgresql\/9.2\/main\/pg_hba.conf\r\n<\/pre>\n<pre lang=\"bash\">\r\npsql -W --user=myuser --host=localhost mydb\r\n<\/pre>\n<p>And execute this code to create a table and save couple of records in our sample database.<\/p>\n<pre lang=\"sql\">\r\ncreate table tbl_test (\r\n  id int,\r\n  name text,\r\n  ts timestamptz,\r\n  info json,\r\n  primary key(id)\r\n);\r\ninsert into tbl_test values (1, 'murat', now(), '{\"a\": \"11\", \"b\": \"21\"}');\r\ninsert into tbl_test values (2, 'yaman', now(), '{\"a\": \"12\", \"b\": \"22\"}');\r\n<\/pre>\n<p>Install Express for Node globally:<\/p>\n<pre lang=\"bash\">\r\nsudo npm install -g express\r\n<\/pre>\n<p>Clone my sample application if you want to.<\/p>\n<pre lang=\"bash\">\r\ngit clone git@github.com:muratyaman\/pgnode.git pgnode-app\r\ncd pgnode-app\r\nvim package.json\r\n<\/pre>\n<p>One of the dependencies is &#8220;pg&#8221; which is the PostgreSQL module for Node.js.<\/p>\n<pre>\r\n{\r\n  \"name\": \"pgnode-app\",\r\n  \"description\": \"Sample app for Node.js and PostgreSQL\",\r\n  \"version\": \"0.0.1\",\r\n  \"private\": true,\r\n  \"scripts\": {\r\n    \"start\": \"node app.js\"\r\n  },\r\n  \"dependencies\": {\r\n    \"express\": \"3.2.6\",\r\n    \"jade\": \"*\",\r\n    \"pg\": \"*\"\r\n  }\r\n}\r\n<\/pre>\n<p>Install any dependencies.<\/p>\n<pre lang=\"bash\">\r\nnpm install\r\n<\/pre>\n<p>Sample code: app.js<\/p>\n<pre lang=\"javascript\">\r\n\r\n\/**\r\n * Module dependencies.\r\n *\/\r\n\r\nvar express = require('express')\r\n  , pg      = require('pg').native\r\n  , routes  = require('.\/routes')\r\n  , user    = require('.\/routes\/user')\r\n  \/\/, test    = require('.\/routes\/test')\r\n  , http    = require('http')\r\n  , path    = require('path')\r\n;\r\n\r\nvar app = express();\r\n\r\n\/\/ all environments\r\napp.set('port', process.env.PORT || 3000);\r\napp.set('views', __dirname + '\/views');\r\napp.set('view engine', 'jade');\r\napp.use(express.favicon());\r\napp.use(express.logger('dev'));\r\napp.use(express.bodyParser());\r\napp.use(express.methodOverride());\r\napp.use(app.router);\r\napp.use(express.static(path.join(__dirname, 'public')));\r\n\r\n\/\/ development only\r\nif ('development' == app.get('env')) {\r\n  app.use(express.errorHandler());\r\n}\r\n\r\n\r\n\/\/--\r\nvar dbUrl = \"tcp:\/\/myuser:123456@localhost\/mydb\";\r\n\r\nfunction disconnectAll() {\r\n    pg.end();\r\n}\r\n\r\nfunction testDate(onDone) {\r\n    pg.connect(dbUrl, function(err, client) {\r\n        client.query(\"SELECT NOW() as when\", function(err, result) {\r\n            console.log(\"Row count: %d\",result.rows.length); \/\/ 1\r\n            console.log(\"Current year: %d\", result.rows[0].when.getFullYear());\r\n\r\n            onDone();\r\n        });\r\n    });\r\n}\r\n\r\nfunction testTable(onDone) {\r\n    pg.connect(dbUrl, function(err, client) {\r\n        client.query(\"CREATE TEMP TABLE reviews(id SERIAL, author VARCHAR(50), content TEXT)\");\r\n        client.query(\"INSERT INTO reviews(author, content) VALUES($1, $2)\",\r\n            [\"mad_reviewer\", \"I'd buy this any day of the week!!11\"]);\r\n        client.query(\"INSERT INTO reviews(author, content) VALUES($1, $2)\",\r\n            [\"calm_reviewer\", \"Yes, that was a pretty good product.\"]);\r\n        client.query(\"SELECT * FROM reviews\", function(err, result) {\r\n            console.log(\"Row count: %d\",result.rows.length); \/\/ 1\r\n            for (var i = 0; i < result.rows.length; i++) {\r\n                var row = result.rows[i];\r\n                console.log(\"id: \" + row.id);\r\n                console.log(\"author: \" + row.author);\r\n                console.log(\"content: \" + row.content);\r\n            }\r\n\r\n            onDone();\r\n        });\r\n    });\r\n}\r\n\r\n\/\/testDate(function() {\r\n\/\/    testTable(disconnectAll)\r\n\/\/});\r\n\r\n\r\nfunction processReqResSql(req, res, sql){\r\n    pg.connect(dbUrl, function(err, client) {\r\n        client.query(sql, function(err, result) {\r\n            var sr = new ServiceResult ('success');\r\n            sr.output = result.rows;\r\n            \/\/for (i = 0; i < result.rows.length; i++) {\r\n            \/\/    sr.output[i] = JSON.parse(result.rows[i].data);\r\n            \/\/}\r\n            res.send(sr);\r\n        });\r\n    });\r\n}\r\n\r\nfunction ServiceResult (status){\r\n    this.ts = new Date();\r\n    this.status = status;\r\n    this.output = new Array();\r\n}\r\n\/\/--\r\n\r\napp.get('\/', routes.index);\r\napp.get('\/users', user.list);\r\napp.get('\/test', \/\/test.list\r\n  function(req, res) {\r\n    var sql = 'select * from tbl_test';\r\n    processReqResSql(req, res, sql);\r\n  }\r\n);\r\n\r\nhttp.createServer(app).listen(app.get('port'), function(){\r\n  console.log('Express server listening on port ' + app.get('port'));\r\n});\r\n<\/pre>\n<p>And run the (server) application.<\/p>\n<pre lang=\"bash\">\r\nnode app\r\n<\/pre>\n<p>On your browser, request the test page:<\/p>\n<pre>\r\nhttp:\/\/yourserver:3000\/test\r\n<\/pre>\n<p>Output should be:<\/p>\n<pre>\r\n{\r\n  \"ts\": \"2013-06-22T19:54:43.413Z\",\r\n  \"status\": \"success\",\r\n  \"output\": [\r\n    {\r\n      \"id\": 2,\r\n      \"name\": \"yaman\",\r\n      \"ts\": \"2013-06-22T18:52:06.136Z\",\r\n      \"data\": {\r\n        \"a\": \"12\",\r\n        \"b\": \"22\"\r\n      }\r\n    },\r\n    {\r\n      \"id\": 1,\r\n      \"name\": \"murat\",\r\n      \"ts\": \"2013-06-22T18:51:58.254Z\",\r\n      \"data\": {\r\n        \"a\": \"11\",\r\n        \"b\": \"21\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n<\/pre>\n<p>You can see the output in JSON including the info field which uses JSON field type (added in PostgreSQL 9.2).<\/p>\n<p>Lovely!<\/p>\n<p>Next step is to create functions in PostgreSQL using PL\/V8. This way I want to keep my server very lightweight and fast. I like my database server as the data gate keeper \ud83d\ude42<\/p>\n<p>Basically, almost every request will execute:<\/p>\n<pre>\r\nSELECT * FROM a_function_name_based_on_request (inputs_in_json_format);\r\n<\/pre>\n<p>And each function will output a row or many rows which will be served as part of the response.<\/p>\n<p><a href=\"https:\/\/github.com\/muratyaman\/pgnode\">https:\/\/github.com\/muratyaman\/pgnode<\/a><\/p>\n<p>Next: <a href=\"http:\/\/www.muratyaman.co.uk\/wp\/index.php\/2013\/09\/postgresql-and-node-js-100-per-cent-javascript-adventure-part-2\/\">Part 2<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a log of every step I will take to create a 100%-JavaScript application back to front.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[93,166,122,33],"class_list":["post-453","post","type-post","status-publish","format-standard","hentry","category-technology","tag-javascript","tag-node","tag-postgresql","tag-sql"],"_links":{"self":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/453","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=453"}],"version-history":[{"count":21,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/453\/revisions"}],"predecessor-version":[{"id":944,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/posts\/453\/revisions\/944"}],"wp:attachment":[{"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.muratyaman.co.uk\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}