Android Login Registration System with Node.js and MongoDB – Server #1

In this series of tutorials we are going to see how to develop a complete android login registration system with Node.js platform and MongoDB document oriented database.

What we will do ?

-> Setup Node.js in Windows and Ubuntu.
-> Registration, Login in Android and Store Data in MongoDB.
-> Reset Password with Email.
-> User Profile page with Gravatar.
-> SHA512 encryption for Passwords.

Why Node.js ?

-> Hottest new technology.
-> Node.js is JavaScript running on the Server.
-> Runs on Chrome V8 JavaScript engine.
-> Its Non blocking and Event driven.
-> Faster than PHP.
-> Does not need additional Server stack such as Apache or NGINX, It has inbuilt http module.
-> JavaScript is easier to learn.
-> Inbuilt Package Manager to install modules.
-> JSON is easier to Use.

Android Login Registration System with Node.js and MongoDB

Node.JS vs Other

Why MongoDB ?

-> NoSQL database.
-> Data is stored in Objects rather than tables in MySQL.
-> Easier to work with Node.js.
-> Stores data in JSON format.

Our tutorial has two major parts

1. Setting up Server with Node.js and MongoDB
2. Develop client side Android application to interact with MongoDB.

Setting up Server Side

Prerequisites

See the following tutorial to setup Node.js and MongoDB in your Linux or Windows machines.

How to Setup Node.js and MongoDB in Ubuntu and Windows

Use the GUI client Robomongo to access MongoDB. It is available for all the platforms.

Download Complete Project

Creating the project

-> Create a MongoDB database named node-android.
-> Create a directory named node-android and change to the directory.
-> Create package.json file and include the following dependencies.

package.json


{     
     "name": "node-android",     
     "version": "0.0.1",     
     "main": "app.js",   
     "dependencies": {       
          "express" : "~4.0.0",       
          "mongoose" : "~3.8.8",      
          "csprng" : "~0.1.1",        
          "connect": "~2.14.4",       
          "nodemailer":"~0.6.3",      
          "crypto":"~0.0.3",      
          "gravatar":"~1.0.6"   
     } 
}

-> Now enter npm install in linux terminal or windows command prompt.
-> Now all the packages begins downloading and it is available in the directory node_modules.

Android Login Registration System with Node.js and MongoDB Android Login Registration System with Node.js and MongoDB

Lets see why we use these packages.

express:

express is a Node.js framework. It is used to simplify some of the basic tasks.

mongoose:

mongoose is a Node.js module which is used to interact easily with MongoDB databases.

csprng:

cspring is used to generate random strings which is used as salt which is used to generate more secure hashed password.

connect:

Connect is a express middleware which is used to parse form data, and to use logger which prints the request in the terminal.

Android Login Registration System with Node.js and MongoDB

Connect Logger

nodemailer:

nodemailer is used to send mail using SMTP for resetting the user password.

crypto:

crypto is a Node.js module used to generate SHA512 hashes.

gravatar:

This simple Node.js module is used to get the Gravatar Image URL of the user.

Continued on Next Page.


Here is the diagram representing Our Project structure in the Server.

Android Login Registration System with Node.js and MongoDB

Creating app.js

Create a file named app.js in the root of the node-android folder. It is the main file which makes our server up and run. Here our application runs on the port 8080 in localhost.

app.js


/**  
 * Module dependencies.  
 */ 
var express  = require('express'); 
var connect = require('connect'); 
var app      = express(); 
var port     = process.env.PORT || 8080;  
// Configuration 
app.use(express.static(__dirname + '/public')); 
app.use(connect.logger('dev')); 
app.use(connect.json()); 
app.use(connect.urlencoded());  
// Routes  

require('./routes/routes.js')(app);  

app.listen(port);  

console.log('The App runs on port ' + port);

 

Setting up routes with routes.js

Our routes.js file handles all the HTTP requests such as GET, POST. We need to create our own routes to handle login, register, change password events, forgot password events. The GET requests are defined by app.get nethod and POST are defined by app.post methods. The functions to handle login, registration and change password are login.js, register.js, chgpass.js which will be placed in config directory inside the node_modules directory. We are importing the defined function using require(”). Login module is imported using require(‘config/login’) . config is the directory of the login module.

For the requests to the URL we would call the function which is predefined to perform the operation. For example for register operation we would post the email and password parameters to the URL http://127.0.0.1:8080/register from our Android Application and Node.js handles the register operation by calling the register function and returns the result back to the user in JSON format.


app.post('/register',function(req,res){ 
var email = req.body.email; // Getting the parameters 
var password = req.body.password;  

register.useremail(email,password,function (found) { //Register function to perform register event 
console.log(found); // Prints the results in Console.(Optional) 
res.json(found); // Returns the result back to user in JSON format 
}); 
});

Similar to register we need to define our routes for other operations. Routes which are not defined are send with 404 error. The complete routes.js which has routes to all the operations. Our routes.js file is placed in the routes directory.

routes.js


var chgpass = require('config/chgpass'); 
var register = require('config/register'); 
var login = require('config/login');   

module.exports = function(app) {        


     app.get('/', function(req, res) {       

          res.end("Node-Android-Project");    
     });     

     app.post('/login',function(req,res){        
          var email = req.body.email;             
               var password = req.body.password;       

          login.login(email,password,function (found) {           
               console.log(found);             
               res.json(found);    
     });    
     });     

     app.post('/register',function(req,res){         
          var email = req.body.email;             
               var password = req.body.password;       

          register.register(email,password,function (found) {             
               console.log(found);             
               res.json(found);    
     });     
     });     

     app.post('/api/chgpass', function(req, res) {       
          var id = req.body.id;                 
               var opass = req.body.oldpass;         
          var npass = req.body.newpass;       

          chgpass.cpass(id,opass,npass,function(found){           
               console.log(found);             
               res.json(found);    
     });     
     });     

     app.post('/api/resetpass', function(req, res) {         

          var email = req.body.email;         

          chgpass.respass_init(email,function(found){             
               console.log(found);             
               res.json(found);    
     });     
     });     

     app.post('/api/resetpass/chg', function(req, res) {         
          var email = req.body.email;         
          var code = req.body.code;       
          var npass = req.body.newpass;       

     chgpass.respass_chg(email,code,npass,function(found){           
          console.log(found);             
          res.json(found);    
     
     });     
     });  
};

Defining MongoDB database Schema

Our schema defines the database stucture. All our data are of String type. It is defined in JSON format. Email is defined such as “email : String”. Connection with MongoDB is established using mongoose.connect(). The connection url is “mongodb://localhost:27017/node-android”. 27017 is the port number of MongoDB. node-android is our Database name. You can also add username and password to your database to make it more secure. The user schema is defined globally in models.js so that we can use easily in all our modules.

models.js


var mongoose = require('mongoose');  

var Schema = mongoose.Schema;  

var userSchema = mongoose.Schema({    
     token : String,     
     email: String,  
     hashed_password: String,    
     salt : String,  
     temp_str:String 
});  

mongoose.connect('mongodb://localhost:27017/node-android'); 
module.exports = mongoose.model('users', userSchema);

Defining register module with register.js

The register module has a global register function which has parameters email, password and a callback. Initially we check whether the Email is valid or not, if not alerts the user. Next is to check the password strengh. The password length should be more than 4, it should contain caps, numbers and a special character. You can change it according to your needs. We are encrypting our data by using salt- a random string added to password and then the password is hashed using SHA512 encryption and then it is stored in the database. A token is also stored which is used to change password. It is very hard to hack these kind of passwords with salt. If the user is sucessfully registered response message is sent as json format.

register.js


var crypto = require('crypto'); 
var rand = require('csprng'); 
var mongoose = require('mongoose'); 
var user = require('config/models');    


exports.register = function(email,password,callback) {  

var x = email; 
if(!(x.indexOf("@")=x.length)){ 
if (password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && password.length > 4 && password.match(/[0-9]/) && password.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)) {  

var temp =rand(160, 36); 
var newpass = temp + password; 
var token = crypto.createHash('sha512').update(email +rand).digest("hex"); 
var hashed_password = crypto.createHash('sha512').update(newpass).digest("hex");  

var newuser = new user({    
     token: token,   
     email: email,   
     hashed_password: hashed_password,   
     salt :temp });  

user.find({email: email},function(err,users){  

var len = users.length;  

if(len == 0){   
     newuser.save(function (err) {   

     callback({'response':"Sucessfully Registered"});  

}); 
}else{    

     callback({'response':"Email already Registered"});  
}});}else{      

     callback({'response':"Password Weak"});  

}}else{    

callback({'response':"Email Not Valid"});  
} 
}  

Defining login module with login.js

In this module login function is defined which takes email, password parameters with callback. The password from the user is added with salt from the database and hashed. The generated hash and hash from database are compared. If its equal return the token to the user with gravatar image url of the users email address in JSON format. If not alert messages are returned.

login.js


var crypto = require('crypto'); 
var rand = require('csprng'); 
var mongoose = require('mongoose'); 
var gravatar = require('gravatar'); 
var user = require('config/models');  

exports.login = function(email,password,callback) {  

user.find({email: email},function(err,users){  

if(users.length != 0){  

var temp = users[0].salt; 
var hash_db = users[0].hashed_password; 
var id = users[0].token; 
var newpass = temp + password; 
var hashed_password = crypto.createHash('sha512').update(newpass).digest("hex"); 
var grav_url = gravatar.url(email, {s: '200', r: 'pg', d: '404'}); 
if(hash_db == hashed_password){  

callback({'response':"Login Sucess",'res':true,'token':id,'grav':grav_url});  

}else{  

callback({'response':"Invalid Password",'res':false});  

} 
}else {  

callback({'response':"User not exist",'res':false});  
} 
}); 
} 

Defining chgpass module with chgpass.js

This module has the functions to change the user password in profile page and reset the password if the user has forgotten his/her password. The cpass function defined is used to change the password in profile page by getting old password, new password and token as parameters. If the old password and the password stored in the database match new password is set or error message is returned.

Next function is the respass_init function which is used to send a random string to the User’s email address to reset the password. We use nodemailer module to send mail using SMTP.

Next function is the respass_chg function which gets the code which is sent as email, new password, email as parameters. If the code matches with the one which is sent new password is set or error is displayed.

chgpass.js


var crypto = require('crypto'); 
var rand = require('csprng'); 
var mongoose = require('mongoose'); 
var nodemailer = require('nodemailer'); 
var user = require('config/models');  

var smtpTransport = nodemailer.createTransport("SMTP",{     
     auth: {         
          user: "[email protected]",        
          pass: "********"        
          } 
});   

exports.cpass = function(id,opass,npass,callback) {  

var temp1 =rand(160, 36); 
var newpass1 = temp1 + npass; 
var hashed_passwordn = crypto.createHash('sha512').update(newpass1).digest("hex");  

user.find({token: id},function(err,users){  

if(users.length != 0){  

var temp = users[0].salt; 
var hash_db = users[0].hashed_password; var newpass = temp + opass; 
var hashed_password = crypto.createHash('sha512').update(newpass).digest("hex");   

if(hash_db == hashed_password){ 
if (npass.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && npass.length > 4 && npass.match(/[0-9]/) && npass.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)) {  

user.findOne({ token: id }, function (err, doc){   
     doc.hashed_password = hashed_passwordn;   
     doc.salt = temp1;   
     doc.save();  

callback({'response':"Password Sucessfully Changed",'res':true});  
}); 
}else{  

callback({'response':"New Password is Weak. Try a Strong Password !",'res':false});  

} 
}else{  

callback({'response':"Passwords do not match. Try Again !",'res':false});  

} 
}else{  

callback({'response':"Error while changing password",'res':false});  

}  

}); 
}  

exports.respass_init = function(email,callback) {  

var temp =rand(24, 24); 
user.find({email: email},function(err,users){  

if(users.length != 0){   

user.findOne({ email: email }, function (err, doc){   
     doc.temp_str= temp;   
     doc.save();  

var mailOptions = {     
     from: "Raj Amal  <[email protected]>",     
     to: email,     
     subject: "Reset Password ",     
     text: "Hello "+email+".  Code to reset your Password is "+temp+".nnRegards,nRaj Amal,nLearn2Crack Team.",  

}  

smtpTransport.sendMail(mailOptions, function(error, response){     
     if(error){  

callback({'response':"Error While Resetting password. Try Again !",'res':false});      

     }else{  

callback({'response':"Check your Email and enter the verification code to reset your Password.",'res':true});      

     } 

}); 
}); 
}else{  

callback({'response':"Email Does not Exists.",'res':false});  

} 
}); 
}  

exports.respass_chg = function(email,code,npass,callback) {   

user.find({email: email},function(err,users){  

if(users.length != 0){  

var temp = users[0].temp_str; 
var temp1 =rand(160, 36); 
var newpass1 = temp1 + npass; 
var hashed_password = crypto.createHash('sha512').update(newpass1).digest("hex");  

if(temp == code){ 
if (npass.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && npass.length > 4 && npass.match(/[0-9]/) && npass.match(/.[!,@,#,$,%,^,&,*,?,_,~]/)) { 

user.findOne({ email: email }, function (err, doc){   
     doc.hashed_password= hashed_password;   
     doc.salt = temp1;   
     doc.temp_str = "";   
     doc.save();  

callback({'response':"Password Sucessfully Changed",'res':true});  

});}else{  

callback({'response':"New Password is Weak. Try a Strong Password !",'res':false});  

} 
}else{  

callback({'response':"Code does not match. Try Again !",'res':false});  

} 
}else{  

callback({'response':"Error",'res':true});  

} 
}); 
}  

Now we have set the server part. Now switch to the root of our project and enter the command node app. Now our app will be running on the port 8080 in localhost. Open the browser and hit 127.0.0.1:8080 you will see the message “Node-Android-Project” in your browser.

Next proceed to the Client part- Developing Android Application.

Raj Amal

Raj Amal

Love to work with Computers, Smartphones, Programming Android. Working @Learn2Crack Learn2Crack

Raj Amal

Raj Amal

Love to work with Computers, Smartphones, Programming Android. Working @Learn2Crack Learn2Crack

This article is by Raj Amal W from learn2crack.com

Implementing Jetty Session Persistence in MongoDB

At SecondMarket, we’re moving towards a development model where not only are the deployments continuous but where deploys incur no downtime. Users should not notice if we take a portion of our servers out for maintenance, even if they’re logged into the site and have an active session. We decided to tackle this problem by persisting Java sessions to external storage. This allows another Jetty to take over serving of existing sessions if we decide to take down a Jetty for maintenance.

Evaluating Options: JDBC, Mongo or Memcache?

There are a number of options for persisting sessions in Jetty to an external engine. The oldest and most well-known technology is to use an SQL database via the JDBC session manager. We already use PostgreSQL as our main relational database, but it’s a critical part of our infrastructure and we weren’t sure we wanted to put session data on the same system; session data definitely doesn’t have the same criticality. We were also concerned about the performance implications of a relational database in this use-case.

Instead, we looked at two NoSQL options via the Jetty NoSQL session plugin available in Jetty 8: MongoDB and memcached. We ultimately settled on MongoDB, not only because it’s the reference implementation for NoSQL sessions but because we have operational experience with MongoDB. (We store some non-critical information in it, like news feeds about companies on the platform.)

Configuring the SessionManager and SessionIDManager

There are two managers to configure in Jetty: the session manager and the ID manager:

  • The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there should only be one session ID manager per Jetty instance.
  • The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.

I decided to configure the session ID manager for each Jetty instance using a separate XML file external to Jetty, calling it jetty-mongo-sessions.xml. This way I could either include or not include it in Jetty’s start.ini as circumstances required. Here’s what I used:


(I’m not a Jetty wizard so I realize I probably could have done this with more <Set> clauses rather than <Call> clauses. Feel free to edit my Gist if you can improve the syntax.)

Naturally, this file is written by Chef. In my Jetty sessions recipe, I do a search on all nodes that are Mongo replicaset members, and dynamically build the ArrayList. I then configure the session manager for each webapp in its context file with something like this:

Odds and Ends

A couple other odds and ends and we’re ready to go:

  • The NoSQL extensions don’t come with the core Jetty distribution, so you have to download them from either Codehaus or Eclipse’s website (depending on which variant you use)
  • The MongoDB Java driver has to appear somewhere in Jetty’s class path. I built an RPM for it that drops it in /usr/share/java, and then I just symlink it into Jetty’s lib directory.
  • start.ini has to include the nosql extensions in OPTIONS= in addition to specifying the jetty-mongo-sessions.xml as another config file to read.

Firing It Up

If you start up Jetty now, it should connect to MongoDB and automatically create both the database and collection to hold the session data.

Pitfalls and Warnings

All this worked fine when we were running on a development environment, but apps started to break once deployed to a clustered Mongo environment. A couple things we discovered:

  • One of our apps is written in Lift and we are using some features of Lift that are incompatible with clustered session storage. For speed, the Lift developers have made these features work only with memory-based sessions, so we have had to turn off Mongo sessions for this app; it can’t be clustered.
  • Mongo is an eventually-consistent database system, so if you’re writing data to a replicaset (master) and then read from a slave, you may or may not get the data you just wrote. That’s because in order for the data to make it to the slave, it has to be written to the master’s journal and then replicated across the wire to the slave. So I’d strongly recommend not turning slaveOkon.
  • More seriously, we discovered that developers were using in-memory sessions to store long-lived objects, rather than using a distributed object cache like EHcache. Session storage is supposed to be a short-lived stack onto which one pushes things needed for the next page view, where they’re popped off. When using in-memory sessions, direct manipulation of the HTTPSession object (via setAttribute()) leads to correct behavior: session data is magically updated. But with NoSQL or JDBC sessions, the session isn’t persisted to the backing store immediately, only when dirty and after the active request count goes to zero. In a distributed cluster without session affinity, this can cause inconsistency: node 1 writes data to the session, the user is sent on their way, only to hit node 2, which tries to read the session from disk & a race condition occurs because the session hasn’t been written there yet by node 1. The long-term solution, of course, will be for us to implement the aforementioned distributed object cache. At the last minute we were forced to set setSavePeriod(-2) in our Jetty config to force session data to be persisted to disk every time setAttribute() is called. (Thanks to my colleague Cal Watson for finding this. He was nominated for, and won, the monthly SecondMarket Peer Bonus award for his -2.)

Conclusion

Using MongoDB as a backing store for session data is absolutely feasible; the NoSQL extensions provided by Jetty are high-quality. In retrospect, with the misuse of session data above, there was no other solution that would have worked for us, so we accidentally happened across the one that was ideal. Had we implemented JDBC (or even Memcache) sessions, we would have been in serious trouble; the sessions collection is about 5.6 GB. This sort of raw, random data turns out to be an excellent fit for Mongo.

Implementing disk-based sessions also moves us one step closer to zero-downtime continuous deploys, and we’re looking forward to cleaning up the rest of our architecture to make that a reality.

Julian C. Dunn

Julian C. Dunn

Product manager at @chef. Interested in tech, startups, urban issues, transportation, journalism. Was a reporter for a hot NY minute. Married to @meredi. JulianDunn.net

This article is by Julian Dunn from juliandunn.net.

Configure remote connection with MongoDb (debian)

Lastest MongoDb package on debian is bind to 127.0.0.1, this address doesn’t allow the connection by remote hosts, to change it u must set bind to 0.0.0.0 for eg
[email protected]:/var/www# nano /etc/mongodb.conf


bind_ip = 0.0.0.0
port = 27017

[email protected]:/var/www/lithium# /etc/init.d/mongodb restart
Done! Remember to secure the connection by password in production mode.

AgBorkowski

AgBorkowski

portfolio http://blog.aeonmedia.eu [eng] .fundation ostatnirejs.pl [pl] Aeon Media

This article is by Andrzej Grzegorz Borkowski from aeonmedia.eu.

MongoDB: Mongodump terminate called after throwing an instance of ‘std::runtime_error’

If you encounter this error:


1.| connected to: 127.0.0.1
2.| Mon Oct 21 10:49:30.638 DATABASE: soft_production to dump/soft_production
3.| terminate called after throwing an instance of 'std::runtime_error'
4.| what(): locale::facet::_S_create_c_locale name not valid
5.| Aborted

Please add this


1.|export LC_ALL=C
2.| # or
3.| export LC_ALL="en_US.UTF-8"

either in the console (for current session) or in .bashrc file.

 

After that you should be ready to go with:


1.| mongodump --db soft_production

Maciej Mensfeld

This article is by Maciej Mensfeld from dev.mensfeld.pl.

Why Programmers Don’t Like Relational Databases

Complaining about relational databases is a staple theme of programmer blogs. Why are so many programmers irritated and frustrated with relational databases? Why do the perceived intricacies of SQL and the “object-relational impedance mismatch” launch so many rants? Why are DBAs more hated than managers? I have some ideas.

Programmers Conflate RDBMSs with SQL
SQL is the standard language for describing, querying, and manipulating data residing in a Relational Database Management System (RDBMS). The deficiencies of SQL, real or imagined, have little to do with relational theory, data integrity, or database management. The SQL language has been criticized by the most distinguished proponents of relational databases. Once you learn relational theory and how (and why) to normalize, SQL’s problems will matter a lot less.

RDBMSs Are Old, Like COBOL and Fortran
Most programmers don’t find databases interesting or fun, so they dismiss databases as “legacy” technology that doesn’t know when it’s time to die. RDBMSs are approximately as old as the C language, and younger than Lisp and Forth, which are trendy again. RDBMSs are still around for two big reasons: There is no serious competing data management technology, and a huge amount of data is committed to RDBMSs. If there was an alternative technology that solved the problems RDBMSs solve so well and offered additional advantages database-based applications would be slowly migrating. Instead we have MySQL and SQLite, low-end open source implementations of 35-year-old technology.

There Are Too Many Incompatible Versions Of SQL
Although SQL is an ANSI standard every vendor has extended the language and implemented parts of the language differently. Oracle’s dialect has some serious deviations from the standard, but then again Oracle and a lot of their installed base pre-date the ANSI standard. The differences between SQL dialects are frequently exaggerated by programmers. In real life converting from one RDBMS to another is such a major undertaking that resolving differences in SQL dialects is only a small part of the problem. Writing a database library that can support multiple RDBMSs is obviously complicated by multiple implementations, but this is a problem with a lot of languages and tools, not specifically an RDBMS or SQL problem.

Who Needs Theory — Just Give Me The Data
Because most of what programmers do has no theoretical basis or system of proof, programmers back away from anything that looks like hard math. Failure to understand and appreciate relational theory has launched countless bad databases (and thousands of witless articles condemning SQL). The idea that there is a right way to design a normalized database–and that the wrong ways are provably wrong–is alien to most programmers. Database management doesn’t come down to a matter of opinion like OOP class hierarchies or coding style.

Most professional programmers know how it feels to see an amateur, unfamiliar with Knuth or any programming book containing equations, implement their own sort routine. That’s how people who understand relational theory feel when they see a badly-designed database. Relational theory and RDBMSs are old and well-established now, so it’s hard not to think a lot of programmers are willfully ignorant.

Relational Databases Don’t Play Nice With My Objects
When OOP took over as the dominant programming paradigm all of the older techniques and technologies were dismissed as bad and unenlightened. In the case of RDBMSs this scorn has a technical name: Object-Relational Impedance Mismatch. RDBMSs can be used as backing store for objects, but mapping object relationships, hierarchies, and references to and from a database is tedious and ugly. A generic code layer to do this (called an Object-Relational Mapping or ORM) is complicated enough, but the incompatibilities of RDBMS vendors and versions (see above) make ORMs really hard to get right. Relational databases are based on sets, not on objects, and relations in a database are based on matching values, not on pointers. There’s definitely an apples vs. oranges problem, but neither technology is necessarily wrong or bad. Object databases may eventually offer a workable solution to the object-relational mismatch, but without a theoretical basis comparable to relational theory it will be hard to make a case for moving valuable data out of RDBMSs.

Some of the most entertaining complaints about the “impedance mismatch” are written by Ruby on Rails advocates–entertaining because by design Rails can’t play nice with legacy databases. The right opinion to have in that community is that legacy databases should be replaced, DBAs should be bypassed by programmers installing MySQL on their own servers, and data integrity should be enforced in every application that uses the data.

Relational Databases Don’t Play Nice With Anything
SQL is a declarative language. Most programmers work with imperative or functional languages, where the code describes how to do something. The SQL SELECT statement may look like a command telling the database which rows (records) to retrieve, but really it’s a description of the relations in the database that satisfy the conditions in the statement. In addition to the imperative/declarative disconnect the data types commonly supported in RDBMSs don’t always map cleanly to the host or calling language. This problem has been around for a long time–OOP just exposed it to a new generation of programmers. One partial solution is embedded SQL, where SQL statements are part of the host language, the types are mapped behind the scenes, and imperative control structures (like loops) can hide RDBMS features like cursors. When tempted to kick RDBMSs out of the playground remember they were probably there first.

Database Administrators (DBAs) Cramp My Style
Companies commit a lot of important and valuable data to RDBMSs, and DBAs are charged with making sure that data is secure, backed up, and protected from programmers deploying broken and untested code. Whatever programmers think of themselves, losing data is just as disastrous as–and frequently more permanent than–a crashing program. Maintaining data integrity is what RDBMSs do, and DBAs are supposed to make sure the RDBMS is allowed to do that. Every DBA I’ve worked with has a lot of stories about programmers losing or corrupting big chunks of valuable data, but programmers mainly complain that DBAs won’t let them do whatever they want. DBAs are called “high priests” and derided as petty tyrants. Some DBAs are incompetent or difficult, but that’s true of programmers, too. A good DBA can design correct, robust databases and help programmers access databases efficiently and safely.

Before flying off the handle about DBAs, consider that the database probably has to support multiple applications, simultaneously, preventing each application from corrupting data or stomping on the other applications. This is a pretty big problem and RDBMSs have offered a workable, scalable solution for a long time.

Recommended Database and SQL Books

Greg Jorgensen

Greg Jorgensen

Itinerant code and database programmer, fixer of broken software and web sites, digital nomad. Typical Programmer

This article is by Greg Jorgensen from typicalprogrammer.com.