Throughout this series we have been incrementally building an external JavaScript stored procedure to parse, and insert JSON-encoded data into a SQL Anywhere database. In this final post, we will modify our procedure to accept JSON strings with more complex embedded objects and arrays. We will also make the procedure available directly through a SQL Anywhere web service.
To make our contact objects more complex we will expand them to include an arbitrary number of phone numbers, segmented into named groups. For example, a sample contact object including phone numbers is:
{ "Surname" : "John", "Given Name" : "Doe", "Date of Birth": "1983-04-04", "Phone": { "work": [ "(555) 555-5555", "(666) 666-6666"], "home": [ "(777) 777-7777"]} }
To facilitate storing the phone groups (i.e. "work", "home", etc) and the individual phone numbers, we will add a couple of tables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | CREATE TABLE "DBA"."PhoneGroups" ( "id" integer NOT NULL DEFAULT autoincrement ,"contact_id" integer NULL ,"name" long varchar NULL ,PRIMARY KEY ("id") ); ALTER TABLE "DBA"."PhoneGroups" ADD FOREIGN KEY "Contacts" ("contact_id") REFERENCES "DBA"."Contacts" ("id"); CREATE TABLE "DBA"."PhoneNumbers" ( "id" integer NOT NULL DEFAULT autoincrement ,"phonegroup_id" integer NULL ,"number" long varchar NULL ,PRIMARY KEY ("id") ); ALTER TABLE "DBA"."PhoneNumbers" ADD FOREIGN KEY "PhoneGroups" ("phonegroup_id") REFERENCES "DBA"."PhoneGroups" ("id"); |
Since we are still only passing a single JSON document (albeit a more complex one) into our JavaScript procedure, we don’t need to modify JsWrapper.java at all. But we do need to modify Contact.js to handle the new phone number fields.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | // this is the equivalent to: import java.sql.* importPackage(java.sql) // ***************** // getIdentity(conn) // ***************** // generic function to return the @@IDENTITY of the last // autoincremented integer var getIdentity = function(conn) { var stmt, retval, rs; stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT @@IDENTITY"); if (rs.next()) { retval = rs.getInt(1); } stmt.close(); return retval; }; // ************************************************* // addPhoneNumber(phonenumbers, phonegroup_id, conn) // ************************************************* // // accepts an array of phone numbers to insert // ex. phonenumbers = [ // "(555) 555-5555", // "(666) 666-6666"]; // var addPhoneNumber = function (phonenumbers, phonegroup_id, conn) { var stmt, i; stmt = conn.prepareStatement( 'INSERT INTO PhoneNumbers("phonegroup_id", "number") VALUES (?, ?)'); for (i = 0; i < phonenumbers.length; i++) { stmt.setInt(1, phonegroup_id); stmt.setString(2, phonenumbers[i]); stmt.executeUpdate(); } stmt.close(); }; // ******************************************** // addPhoneGroup(phonegroups, contact_id, conn) // ******************************************** // accepts a hash of phone groups to insert // ex. phonegroups = { // "work": [ // "(555) 555-5555", // "(666) 666-6666"], // "home": [ // "(777) 777-7777", // "(888) 888-8888"]}; // var addPhoneGroup = function (phonegroups, contact_id, conn) { var stmt, group; stmt = conn.prepareStatement( 'INSERT INTO PhoneGroups("contact_id", "name") VALUES (?, ?)'); for (group in phonegroups) { stmt.setInt(1, contact_id); stmt.setString(2, group); stmt.executeUpdate(); addPhoneNumber(phonegroups[group], getIdentity(conn), conn); } stmt.close(); }; // ************************* // addContact(contact, conn) // ************************* // accepts an array of contact object to insert // ex. contact = { // "Surname": "Washington", // "Given Name": "George", // "Date of Birth": "1732-02-22", // "Phone": { // "work": [ // "(555) 555-5555", // "(666) 666-6666"], // "home": [ // "(777) 777-7777", // "(888) 888-8888"]}}; // var addContact = function (contact, conn) { var stmt, i; // create a prepared statement for inserting contacts stmt = conn.prepareStatement( 'INSERT INTO Contacts("surname", "givenName",' + '"birthDate") VALUES (?, ?, ?)'); for (i in contact) { // iterate through contact list and insert contacts stmt.setString(1, contact[i]["Surname"]); stmt.setString(2, contact[i]["Given Name"]); stmt.setString(3, contact[i]["Date of Birth"]); stmt.executeUpdate(); addPhoneGroup(contact[i].Phone, getIdentity(conn), conn); } stmt.close(); }; // get handle to the default JDBC connection var jdbc_conn = DriverManager.getConnection("jdbc:default:connection"); // add all the contacts from the passed JSON contact array addContact(JSON.parse(arguments[0]), jdbc_conn); // commit the transaction jdbc_conn.commit(); |
Compile Contact.js (as explained in a previous post), and update the resultant .JAR file in the database.
1 | INSTALL JAVA UPDATE FROM FILE 'Contact.class'; |
The last thing we need to do is create a web service to wrap our JavaScript procedure. (You will need to have the SQL Anywhere HTTP running in order for this to work. Read this post for information on starting the HTTP server). The following code defines a web service called /contact that accepts POST requests. The POST body should be a JSON-encoded list of contacts.
1 2 3 4 5 6 7 8 | CREATE SERVICE "contact" TYPE 'RAW' AUTHORIZATION OFF SECURE OFF URL PATH OFF USER "DBA" METHODS "POST" AS CALL InsertContactList(HTTP_BODY()); |
To test this out we will need to send a POST request to our newly-created web service. The easiest way I have found to do this is using the cURL command-line tool.
curl http://localhost:8080/contact -X POST -d "
[{
\"Surname\" : \"John\",
\"Given Name\" : \"Doe\",
\"Date of Birth\": \"1983-04-04\",
\"Phone\": {
\"work\": [
\"(555) 555-5555\",
\"(666) 666-6666\"],
\"home\": [
\"(777) 777-7777\"]}
}]"Lastly, check that everything was inserted properly using this query.
1 2 3 4 | SELECT givenName, surName, name, number FROM Contacts, PhoneGroups, PhoneNumbers WHERE Contacts.id = PhoneGroups.contact_id AND PhoneGroups.id = PhoneNumbers.phonegroup_id; |
The result set should contain all three of John Doe’s phone numbers.











0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment
Note that all comments are currently being moderated until I have a better handle on spam, so your comment may not appear for a couple of hours