This is going to be a pretty short post, but I thought it would be fun to share this in light of the Twilio + DEV hackathon this month. Honestly, I'm not sure if either project I planned out will be finished in time. This month went by way too fast, so the outlook is not good.
If you are unfamiliar with IBMi and have a few minutes to read, I encourage you to glance over a previous subpar post. If not, it doesn't really matter; its not critical to looking at a couple blocks of SQL.
This image is IBMi in a nutshell. It either disgusts or fascinates a younger developer; it is what it is.
Since I'm still a pretty new IBMi developer, I found that the best way to learn this new world was to take a fun idea and see if it was possible to do with RPG and/or DB2 SQL.
Now I have a handful of arguably useless code snippets for my day job lol...
Example HTTP Request in DB2 for i
One of the major things that made me fall in love with IBMi was that DB2 was really versatile. The fact that I could easily send HTTP requests with SQL was mind blowing.
For a really basic example, I'm going to do a basic HTTP GET to the GitHub REST API v3 for my user using only SQL. The equivalent CURL command will be
#!/bin/bash
curl -i https://api.github.com/users/barrettotte
This HTTP request is super simple because we don't need any HTTP headers.
values SysTools.HttpGetClob(
cast('https://api.github.com/users/barrettotte' as varchar(128)), -- url
cast(null as clob) -- http headers
);
The request returns
00001 |
---|
'{"login":"barrettotte","id":15623775,"node_id"...}' |
Ok. That's cool because we can parse the JSON string in another program or something. But, actually we can do some way cooler stuff. We can return the HTTP response as a result set.
Here is a really basic example, I mostly just used varchars for simplicity, but any field could be mapped to any appropriate data type.
select *
from json_table(
SysTools.HttpGetClob(
cast('https://api.github.com/users/barrettotte' as varchar(128)),
cast(null as clob)
),
'$' columns(
login varchar(64) path 'lax $.login',
id varchar(16) path 'lax $.id',
node_id varchar(32) path 'lax $.node_id',
avatar_url varchar(64) path 'lax $.avatar_url',
url varchar(64) path 'lax $.url',
html_url varchar(64) path 'lax $.html_url',
followers_url varchar(64) path 'lax $.followers_url',
following_url varchar(64) path 'lax $.following_url',
gists_url varchar(64) path 'lax $.gists_url',
starred_url varchar(64) path 'lax $.starred_url',
subs_url varchar(64) path 'lax $.subscriptions_url',
orgs_url varchar(64) path 'lax $.organizations_url',
repos_url varchar(64) path 'lax $.repos_url',
events_url varchar(64) path 'lax $.events_url',
rcv_events_url varchar(64) path 'lax $.received_events_url',
type varchar(16) path 'lax $.type',
site_admin varchar(8) path 'lax $.site_admin',
name varchar(64) path 'lax $.name',
company varchar(64) path 'lax $.company',
blog varchar(64) path 'lax $.blog',
location varchar(64) path 'lax $.location',
email varchar(64) path 'lax $.email',
hireable varchar(8) path 'lax $.hireable',
bio varchar(512) path 'lax $.bio',
public_repos int path 'lax $.public_repos',
public_gists int path 'lax $.public_gists',
followers int path 'lax $.followers',
following int path 'lax $.following',
created_at varchar(32) path 'lax $.created_at',
updated_at varchar(32) path 'lax $.updated_at'
)
);
The request returns
LOGIN | ID | NODE_ID | ... |
---|---|---|---|
barrettotte | 15623775 | MDQ6VXN... | ... |
Personally I think this is really neat.
Calling Twilio from DB2 SQL
I figured I should say I know that this is not an ideal solution for probably a majority of cases. But, this is just a fun thing I'm showing.
The HTTP request I'm going to make looks like this
POST {{base}}/2010-04-01/Accounts/{{account}}/Messages.json HTTP/1.1
Authorization: Basic {{account}}:{{auth}}
Accept: application/json
Content-Type: application/x-www-form-urlencoded
To={{to}}&From={{from}}&Body=Hello+World
Calling Twilio takes a few more steps than the previous example. In DB2 for i, you have to pass HTTP headers as XML (I assume its a legacy thing and I wish it was JSON, but its still easy to work with).
The authorization header has to be passed as a Base64 encoded string. There is a scalar function called Base64Encode in SysTools that seems to work fine.
Additionally, Twilio wants the request body as a url-encoded string. To my surprise, I learned that SysTools also has a scalar function called UrlEncode. All of the hard work is done with scalar functions, you just have to piece them together.
I replaced all secrets in this query with 'variables' surrounded by double curly braces.
select *
from json_table(
SysTools.HttpPostClob(
'https://api.twilio.com/2010-04-01/Accounts/{{account}}/Messages.json',
cast((
'<httpHeader>
<header name="Authorization" value="Basic ' || trim(SysTools.Base64Encode(
cast('{{account}}:{{auth}}' as varchar(256) ccsid 1208))) ||
'"/>
<header name="Accept" value="application/json"/>
<header name="Content-Type" value="application/x-www-form-urlencoded"/>
</httpHeader>'
) as clob),
cast((
'To=' || SysTools.UrlEncode('{{to}}', 'UTF-8') ||
'&From=' || SysTools.UrlEncode('{{from}}', 'UTF-8') ||
'&Body=' || SysTools.UrlEncode('Hello World', 'UTF-8')
) as clob)
),
'$' columns(
sid varchar(64) path 'lax $.sid',
date_created varchar(64) path 'lax $.date_created',
date_updated varchar(64) path 'lax $.date_updated',
date_sent varchar(64) path 'lax $.date_sent',
account_sid varchar(64) path 'lax $.account_sid',
phone_to varchar(32) path 'lax $.to',
phone_from varchar(32) path 'lax $.from',
msg_srv_sid varchar(64) path 'lax $.messaging_service_sid',
body varchar(1600) path 'lax $.body',
status varchar(16) path 'lax $.status',
num_segments varchar(8) path 'lax $.num_segments',
num_media varchar(8) path 'lax $.num_media',
direction varchar(32) path 'lax $.direction',
api_version varchar(16) path 'lax $.api_version',
price varchar(8) path 'lax $.price',
price_unit varchar(4) path 'lax $.price_unit',
error_code varchar(8) path 'lax $.error_code',
error_message varchar(512) path 'lax $.error_message',
uri varchar(256) path 'lax $.uri',
nested '$.subresource_uris[*]' columns(
media varchar(256) path 'lax $.media'
)
)
);
The request returns
SID | DATE_CREATED | DATE_UPDATED | DATE_SENT | ACCOUNT_SID | PHONE_TO | ... |
---|---|---|---|---|---|---|
... | Wed, 22 Apr 2020 23:35:26 +0000 | ... | ... | ... | ... | ... |
Conclusion
That's kind of it, I thought it was pretty cool and figured I'd share it for anyone browsing around this morning.
The gist can be found here
Realistically, I don't know what you would do with this. But, knowing that it exists "might" do some good in some situation.
Top comments (0)