Communities
|
Social Applications
Networks
Support
|
|
C-Level Executives
Other Roles
|
|
Support
Education
Partner
Other Tasks
|
Articles
Developer: PL/SQL
Twitter Meets Oracle: ORA_TweetBy Lewis Cunningham Teach your database to "tweet" its status updates to a private account. In my search for fun and exciting things to do with an Oracle database—call them “stupid database tricks”—I often find myself, in the deepest, darkest hours of the night, happily hacking away at things that might not matter to anyone but a geek. Sometimes, though, my excursions result in tools that could be useful for the masses. Such is the case with ORA_Tweet, a PL/SQL procedure that lets you create Twitter posts from inside your database. What could be the possible use case, you might ask? Well, as you probably do, I often initiate long-running processes. Currently, I have the database email me a status report when the process is finished. But even better, with ORA_Tweet, I can have the database tweet its status to me—a short and sweet “it succeeded”" or “it failed” message (with more details about any failure emailed to me). It almost goes without saying, but I'll say it anyway: As with many other things you read on OTN, use the code here at your own risk; it has not been validated by Oracle and will not be supported by Oracle. What is Twitter?To understand the usefulness of an interface to Twitter, you need to know exactly what Twitter is. The short answer is: I'm not really sure. It's sort of like IM but without the expectation that any particular person will be there to answer. It's very public. If you start your day off with a "Hello, Mom", everyone who “follows” you (that is, who has configured their feed to include your messages) will see it. This capability is sometimes called “micro-blogging”.
Messages on Twitter are called “tweets” and cannot be longer than 140 characters. Trying to follow a conversation that is spread over multiple tweets can be difficult.
The Twitter APITo make calls to Twitter from a database, one needs a method for plugging into Twitter. Fortunately for us, Twitter provides an
API for performing almost any interaction that you might wish for, including the ability to post a tweet.
The return value from a status update is not particularly important. As long as you don't get an error, then your update was probably successful. The most likely reason for an error will be an invalid user name or password.
<status> created_at id text source truncated in_reply_to_status_id in_reply_to_user_id favorited <user> id name screen_name description location profile_image_url url protected followers_count The DatabaseI think that's enough about the Twitter API for now. Let's talk about the goal of our little project. I want to be able to update my status by calling a PL/SQL stored procedure. I run Oracle Database XE, 10g Release 2, and 11g databases but there is no reason this code can't work on any Oracle data from the last decade or so. The bulk of the code will be created by making calls to the built-in package UTL_HTTP. UTL_HTTPUTL_HTTP is a PL/SQL implementation of an HTTP requestor (or client). With UTL_HTTP you can make calls to a Web server and return the results to your database. What this means is that the Oracle database has had the ability to access Web services for many years; it was introduced in a limited form in Oracle8.
Putting It TogetherNow we put the code together. The goal here is to make it as simple to use as possible but also make it easy to enhance. I am packaging up the procedure as I think it makes a lot of sense to use a package even when you will only have a single procedure. When it comes time to extend the functionality, the package will just make life easier.
The Spec
/
Short and sweet. Notice that the proxy url and domain list are both optional. The BodyI will post the body below and explain each section. The full body is listed below that.
CREATE OR REPLACE PACKAGE BODY ora_tweet
AS
/* ORA_TWEET
Author: Lewis Cunningham
Date: Marchish, 2009
Email: lewisc@rocketmail.com
Twitter: oracle_ace
Web: http://database-geek.com
License: Free Use
Version: 1.1
*/
twit_host VARCHAR2(255) := 'twitter.com';
twit_protocol VARCHAR2(10) := 'http://';
-- URL for status updates
tweet_url VARCHAR2(255) := '/statuses/update.xml';
This is the header of the package body. The combination of twit_protocol, twit_host, and tweet_url make up the status update url. I separated the components so that future functionality could more easily be added. At this point, these could all be put into a single variable.
FUNCTION tweet
(
p_user IN VARCHAR2,
p_pwd IN VARCHAR2,
p_string IN VARCHAR2,
p_proxy_url IN VARCHAR2 DEFAULT NULL,
p_no_domains IN VARCHAR2 DEFAULT NULL )
RETURN BOOLEAN
AS
The procedure declaration matches the spec. v_req UTL_HTTP.REQ; -- HTTP request ID v_resp UTL_HTTP.RESP; -- HTTP response ID v_value VARCHAR2(1024); -- HTTP response data v_status VARCHAR2(160); -- Status of the request v_call VARCHAR2(2000); -- The request URLThe procedure variables. These will make more sense once we move into the code.
-- Twitter update url
v_call := twit_protocol ||
twit_host ||
tweet_url;
The above code creates the fully fleshed out request URL.
-- encoded status tring
v_status := utl_url.escape(
url => 'status=' || SUBSTR(p_string,1,140))
You may have spaces or special characters in your status update. The escape function replaces those with more acceptable characters. Notice that the string include a "status=" at the beginning. When this is added to the final URL, it will look like "?status=status update text".
-- Authenticate via proxy
This is the proxy call. The format of the URL is specified in the comments. If your proxy does not need the user name and password, you can leave that off (and leave off the @). You can add an additional :port should you require it.
-- Has to be a POST for status update
v_req := UTL_HTTP.BEGIN_REQUEST(
url => v_call,
method =>'POST');
This call begins the request but still has not sent any specific data to the request beyond that it is a POST action.
-- Pretend we're a moz browser
UTL_HTTP.SET_HEADER(
r => v_req,
name => 'User-Agent',
value => 'Mozilla/4.0');
-- Pretend we're coming from an html form
UTL_HTTP.SET_HEADER(
r => v_req,
name => 'Content-Type',
value => 'application/x-www-form-urlencoded');
The three calls above send information that tells the Web site that the call is coming from a Mozilla browser, from a Web form, and that the data is of a certain length. This is about the minimal amount of information that you should send a Web site.
-- authenticate with twitter user/pass
UTL_HTTP.SET_AUTHENTICATION(
r => v_req,
username => p_user,
password => p_pwd );
Here we are sending the Twitter user name and password. This is how we log into the system.
-- Send the update
UTL_HTTP.WRITE_TEXT(
r => v_req,
data => v_status );
Here we send the v_status variable as a variable to the URL. This is the data that Twitter is expecting.
-- Get twitter's update
v_resp := UTL_HTTP.GET_RESPONSE(
r => v_req);
The code above gets the Twitter response, loops through, displays it and finally, after the loop, closes the request. We return TRUE to show that we send the request and did not get an exception on the response. We end with the exception handler.
EXCEPTION
The UTL_HTTP.END_OF_BODY exception is a normal and expected exception. In the response loop, when you hit the end of the data, Oracle raises this exception. The WHEN others to catch any unexpected exceptions.
That's all of it. It really isn't that much code. Oracle, or I should say PL/SQL, really makes the process easy. It's one of the reasons I love PL/SQL so much. Using ORA_TweetThe first thing to do is to set up a Twitter account for your messages. You may want to setup a special Twitter account for this purpose, rather than using your primary account. I don’t think the people who follow you really want to see when your processes are finished. If you are concerned about others seeing your messages, you can protect your account so that only you can see the tweets. You can then follow that account and view the messages as they come across. The CallTo call the procedure, you would have a block something like the following:
SET SERVEROUTPUT ON
You don’t need to have serveroutput on unless you want to see the entire response. I display the results from the call for debugging purposes. Once you have tested and get it to your satisfaction, you can get rid of the set serverout call. With serveroutput on, the results look like this:
Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
<?xml version="1.0" encoding="UTF-8"?>
<status>
<created_at>Sun Mar 15 13:53:15 +0000 2009</created_at>
<id>1331361038</id>
<text>ora_tweet v1.0 is complete!</text>
<source>web</source>
<truncated>false</truncated>
<in_reply_to_status_id></in_reply_to_status_id>
<in_reply_to_user_id></in_reply_to_user_id>
<favorited>false</favorited>
<in_reply_to_screen_name></in_reply_to_screen_name>
<user>
<id>24484454</id>
<name>lewis cunningham</name>
<screen_name>ora_tweet</screen_name>
<location></location>
<description></description>
<profile_image_url>
http://static.twitter.com/images/default_profile_normal.png
</profile_image_url>
<url></url>
<protected>false</protected>
<followers_count>1</followers_count>
</user>
</status>
Success!
PL/SQL procedure successfully completed.
If you see a different type of message, say like an authentication error, you probably have the wrong password or spelled your username wrong. I’ve only spent about an hour on this so the exception handling is not especially robust but it suffices for most needs. Lewis Cunningham is an Oracle ACE Director and currently works for JP Morgan Chase in Tampa, Fla. Lewis has been coding cool PL/SQL tools and applications since 1993. When he's not coding, you'll probably find him writing. Follow his database adventures at database-geek.com and his adventures in the cloud at clouddb.info. You can follow his tweets at www.twitter.com/oracle_ace. |
||||||||||||||||||||||||||||||||||||||||||
