Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
commit 08f440e17bc2c6bd0eff6a180ffe264692df83b1 Author: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat Aug 12 14:57:06 2023 +0000 [Automation] Site update No.14 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ + diff --git a/404.html b/404.html new file mode 100644 index 0000000..d5f98ab --- /dev/null +++ b/404.html @@ -0,0 +1 @@ +
Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
A new version of content is available.

Hi my name is Cole and I am a growing software engineer. I am currently studying Computer Science at the University of Minnesota, Morris.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
If you are new to the IBM i platform coming right out of school, like me, or you are a developer used to working exclusively with open-source tooling, the IBM i platform can be a strange place. The...
The Api This demo used the fakeStoreApi which is a free online REST API that you can use whenever you need Pseudo-real data for without running any server-side code. Itās awesome for teaching purp...
A new version of content is available.
If you are new to the IBM i platform coming right out of school, like me, or you are a developer used to working exclusively with open-source tooling, the IBM i platform can be a strange place. The legacy application support is industry leading, to both the benefit and downside of the platform. Under the hood there is IBMās powerful and well tested relational database, DB2 for i. So far, I like what I see. Is it possible to get the best of the open-source tooling while leveraging the power of an existing enterprise grade database? My initial take is yes, and the ODBC driver on the platform is the answer.
The Open Database Connectivity (ODBC) standard is an application programming interface (API) for accessing database management systems (DBMS). The designers of ODBC aimed to make it independent of database systems and operating systems. From what I have seen so far IBM is continuing to make improvements to the driver in the latest release of IBM i. I personally view ODBC as the future of the platform and a key factor to help IBM i remain relevant as the years progress.
As I have gotten my start, the other open-source advocates on the IBM i platform have provided many excellent articles, source code examples, and video lessons that have aided my on boarding to the platform. However, even though the topic of ODBC has been extensively covered I still felt like a comprehensive guide for connecting locally to DB2 for i via ODBC on a linux development machine was missing.
This post has compiled the good, but scattered, information to explain how an open-source developer would go about connecting up their local linux machine to DB2 for i to develop an application in an open-source language of their choice. I want to give a big thank you and credit to Liam Allan, Kevin Adler, Seiden Group, and FormaServe for helping get this information out to the community. They are the heavy hitters aiding the open-source embracement on IBM i. Much of the following is copied directly from their blogs and video resources. Please see the references at the end of this post.
You must have the ODBC driver installed on the IBM i you want to connect to. See Seiden Groupās guide1 for Using YUM to Install or Update the IBM i ODBC Driver
If your background is exclusively developing on the IBM i (AS400) and you donāt have experience with Linux or other Unix-like operating systems you may want to spend some time reading about the basic file structure of Unix-like operating systems. You will find these patterns in the /QOpenSys directory on IBM i and it will aid your journey to better understand open-source on IBM i and even Linux.
IBM has made RPM and DEB package manager repositories for Linux available directly from IBM for the IBM i Access Client Solutions application package, which includes the IBM i Access ODBC driver.
With this change, it is much easier to install the driver on Linux. It also makes it easier for automation to install the driver as well, whether thatās Ansible system deployment scripts or Dockerfiles for building ODBC-based Linux container apps. In addition, it makes updating the driver much easier too, since the process uses the same upgrade procedure as the rest of the system packages2.
The repositories are located under: https://public.dhe.ibm.com/software/ibmi/products/odbc/.
First, you must add IBMās package repository to your distributionās package manager.
1
+
curl https://public.dhe.ibm.com/software/ibmi/products/odbc/debs/dists/1.1.0/ibmi-acs-1.1.0.list | sudo tee /etc/apt/sources.list.d/ibmi-acs-1.1.0.list
+
1
+
curl https://public.dhe.ibm.com/software/ibmi/products/odbc/rpms/ibmi-acs.repo | sudo tee /etc/yum.repos.d/ibmi-acs.repo
+
1
+
curl https://public.dhe.ibm.com/software/ibmi/products/odbc/rpms/ibmi-acs.repo | sudo tee /etc/zypp/repos.d/ibmi-acs.repo
+
Now install the package via the distributionās package manager.
1
+2
+
sudo apt update
+sudo apt install ibm-iaccess
+
1
+
sudo dnf install --refresh ibm-iaccess
+
1
+2
+
sudo zypper refresh
+sudo zypper install ibm-iaccess
+
Now that you have the IBM i Access ODBC Driver installed on your system, you are ready to connect to Db2 on i. Below is some background information on the two methods to create a connection.
ODBC uses a connection string with keywords to create a database connection. Keywords are case insensitive, and values passed are separated from the keyword by an equals sign (ā=ā) and end with a semi-colon (ā;ā). As long as you are using an ODBC database connector, you should be able to pass an identical connection string in any language or technology and be confident that it will correctly connect to Db2 on i. A common connection string may look something like3:
1
+
DRIVER=IBM i Access ODBC Driver;SYSTEM=my.ibmi.system;UID=foo;PWD=bar;
+
In the above example, we define the following connection options:
These are only some of the over 70 connection options you can use when connecting to Db2 on i using the IBM i Access ODBC Driver. A complete list of IBM i Access ODBC Driver connection options can be found at the IBM Knowledge Center: Connection string keywords webpage. If passing connections options through the connection string, be sure to use the keyword labeled with Connection String.
As you add more and more options to your connection string, your connection string can become quite cumbersome. Luckily, ODBC offers another way of defining connection options called a DSN (datasource name). Where you define your DSN will depend on whether you are using Windows ODBC driver manager or unixODBC on Linux or IBM i3.
IBM i, Linux distributions, and macOS use unixODBC and have nearly identical methods of setting up your drivers and your DSNs.
odbc.ini and .odbc.ini
When using unixODBC, DSNs are defined in odbc.ini and .odbc.ini (note the . preceding the latter). These two files have the same structure, but have one important difference:
odbc.ini defines DSNs that are available to all users on the system. If there are DSNs that should be available to everyone, they can be defined and shared here. Likely, this file is located in the default location, which depends on whether you are on IBM i or Linux:
IBM i: /QOpenSys/etc/odbc.ini
Linux: /etc/unixODBC/odbc.ini
If you want to make sure, the file can be found by running:
1
+
odbcinst -j
+
.odbc.ini is found in your home directory ~/ and defines DSNs that are available only to you. If you are going to define DSNs with your personal username and password, this is the place to do it.
In both odbc.ini and .odbc.ini, you name your DSN with [] brackets, then specify keywords and values below it. An example of a DSN stored in ~/.odbc.ini used to connect to an IBM i system with private credentials might look like:
1
+2
+3
+4
+5
+6
+7
+8
+9
+
[MYDSN]
+Description = My IBM i System
+Driver = IBM i Access ODBC Driver
+System = my.ibmi.system
+UserID = foo
+Password = bar
+Naming = 0
+DefaultLibraries = MYLIB
+TrueAutoCommit = 1
+
In the above example, we define the following connection options:
Like connection string keywords, DSN keywords can be found at the IBM Knowledge Center: Connection string keywords webpage. When passing connection options through a DSN, be sure to use the keyword labeled with ODBC.INI.
.odbc.ini file1
+
touch .odbc.ini
+
UserID and Password to your IBM i username and password.1
+2
+3
+4
+5
+6
+7
+8
+
[devserver]
+Description = Connection to development power server
+Driver = IBM i Access ODBC Driver
+System = devserver.mycompany.com
+UserID = myUsername
+Password = myPassword
+Naming = 0
+DefaultLibraries = businessDataLib,myUserLib,myBusinessUtils
+
In the above example, we define the following connection options:
0 indicates you want SQLs naming convention, which is likely what you want for running queries in any program you write.The isql command is included with the open source components of unixODBC and unixODBC-devel. You can use this command to run SQL queries via ODBC right from the command-line. To make the connection to the DSN configured above pass in the DSN name:
1
+
isql devserver
+
If the connection is configured correctly, you will get a prompt that looks like this:
1
+2
+3
+4
+5
+6
+7
+8
+9
+
+---------------------------------------+
+| Connected! |
+| |
+| sql-statement |
+| help [tablename] |
+| quit |
+| |
++---------------------------------------+
+SQL>
+
There is an included sample customer table (qiws.qcustcdt) on all IBM i systems that can be used for testing4
Type this command into the SQL> prompt:
1
+
select * from qiws.qcustcdt
+
The results will look like this:
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
SQL> select * from qiws.qcustcdt
++---------+---------+-----+--------------+-------+------+--------+-------+-------+---------+---------+
+| CUSNUM | LSTNAM | INIT| STREET | CITY | STATE| ZIPCOD | CDTLMT| CHGCOD| BALDUE | CDTDUE |
++---------+---------+-----+--------------+-------+------+--------+-------+-------+---------+---------+
+| 938472 | Henning | G K | 4859 Elm Ave | Dallas| TX | 75217 | 5000 | 3 | 37.00 | 0 |
+| 839283 | Jones | B D | 21B NW 135 St| Clay | NY | 13041 | 400 | 1 | 100.00 | 0 |
+| 392859 | Vine | S S | PO Box 79 | Broton| VT | 5046 | 700 | 1 | 439.00 | 0 |
+| 938485 | Johnson | J A | 3 Alpine Way | Helen | GA | 30545 | 9999 | 2 | 3987.50 | 33.50 |
+| 397267 | Tyron | W E | 13 Myrtle Dr | Hector| NY | 14841 | 1000 | 1 | 0 | 0 |
+| 389572 | Stevens | K L | 208 Snow Pass| Denver| CO | 80226 | 400 | 1 | 58.75 | 1.50 |
+| 846283 | Alison | J S | 787 Lake Dr | Isle | MN | 56342 | 5000 | 3 | 10.00 | 0 |
+| 475938 | Doe | J W | 59 Archer Rd | Sutter| CA | 95685 | 700 | 2 | 250.00 | 100.00 |
+| 693829 | Thomas | A N | 3 Dove Circle| Casper| WY | 82609 | 9999 | 2 | 0 | 0 |
+| 593029 | Williams| E D | 485 SE 2 Ave | Dallas| TX | 75218 | 200 | 1 | 25.00 | 0 |
+| 192837 | Lee | F L | 5963 Oak St | Hector| NY | 14841 | 700 | 2 | 489.50 | .50 |
+| 583990 | Abraham | M T | 392 Mill St | Isle | MN | 56342 | 9999 | 3 | 500.00 | 0 |
++---------+---------+-----+--------------+-------+------+--------+-------+-------+---------+---------+
+SQLRowCount returns -1
+12 rows fetched
+SQL>
+
To exit the prompt press Ctr + C or type quit into the prompt
Now that you have the ODBC driver installed and configured on you development machine you can use the ODBC drivers in many of your favorite open-source programing languages. See IBMās Db2 for Developers page for supported languages.
Examples of connections in programing languages:
Seiden Group: USING YUM TO INSTALL OR UPDATE THE IBM i ODBC DRIVERĀ ↩
Kevin Adler: IBM-provided Repositories ODBC Linux Driver RepositoriesĀ ↩
FormaServe: How to use ODBC on the IBM iĀ ↩
A new version of content is available.
This demo used the fakeStoreApi which is a free online REST API that you can use whenever you need Pseudo-real data for without running any server-side code. Itās awesome for teaching purposes, sample codes, tests, etc. This API does not require authentication for requests
A list of other public APIs can be found here
These HTTP functions are used to make HTTP requests that use web services. These functions allow the SQL programmer to use Representational State Transfer (RESTful) via SQL, including Embedded SQL. They provide the same capabilities as the SYSTOOLS HTTP functions without the overhead of creating a JVM.
These HTTP functions exist in QSYS2 and have lower overhead than the SYSTOOLS HTTP functions. Additional benefits of the QSYS2 HTTP functions are HTTP authentication, proxy support, configurable redirection attempts, and configurable SSL options.
The URL parameter supports http: and https: URLs. The https: URL indicates that network communication should take place over a secure communication channel. An https request uses TLS (Transport Layer Security) to create the secure channel. This secure channel encrypts any transmitted data and also prevents man-in-the-middle attacks. Any communication that contains secure information should use https instead of http. Because of the sensitive nature of userids and passwords, HTTP authentication is not allowed for http URLs.
The foundational functions are named according to the two dimensions used when making HTTP requests. The first dimension is the HTTP operation. There are 5 different HTTP operations: GET, PUT, POST, PATCH, and DELETE. The second dimension indicates whether the verbose version of the function should be used. The non-verbose functions are scalar functions that return the response as a CLOB. The verbose functions are table functions that return a single row, which includes the return header information that is sent from the HTTP server. The header information is formatted as JSON. The names of the functions reflect these dimensions. For example, HTTP_GET_VERBOSE uses the GET operation from the first dimension and the VERBOSE setting from the second dimension. All the functions return CLOB data.
See the IBM Docs for more details
The first demo receives a list of products from the fakeStoreApi as JSON. Here is a look at the JSON we can expect to receive:
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
+
[
+ {
+ "id": 1,
+ "title": "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
+ "price": 109.95,
+ "description": "Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday",
+ "category": "men's clothing",
+ "image": "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg",
+ "rating": {
+ "rate": 3.9,
+ "count": 120
+ }
+ },
+ {
+ "id": 2,
+ "title": "Mens Casual Premium Slim Fit T-Shirts ",
+ "price": 22.3,
+ "description": "Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.",
+ "category": "men's clothing",
+ "image": "https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg",
+ "rating": {
+ "rate": 4.1,
+ "count": 259
+ }
+ }
+]
+
This is actually an array of two JSON objects. The JSON tools provided by DB2 are smart and will know to treat each object separately. To make sure we are getting the expected JSON we can print the results of QSYS2.HTTP_GET with the VALUES keyword.
1
+2
+3
+4
+
VALUES QSYS2.HTTP_GET(
+ 'http://fakestoreapi.com/products?limit=2',
+ ''
+ );
+
QSYS2.HTTP_GET takes two arguments. The first argument is the URL of the API endpoint the GET request will be sent to. In this case it is the http://fakestoreapi.com/products endpoint and the limit=2 parameter is added to only get two items total. The second argument is for HTTP header parameters. In this case no HTTP header parameters need to be specified to complete the request so this field can be left empty.
The JSON_TABLE function can take any QSYS2.HTTP_XXXX that produces JSON as an argument. The values from the JSON keys can then be extracted and placed directly into a table.
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+
SELECT *
+FROM JSON_TABLE(
+ QSYS2.HTTP_GET(
+ 'http://fakestoreapi.com/products?limit=10',
+ ''
+ ),
+ '$' COLUMNS(
+ name VARCHAR(75) PATH 'lax $.title',
+ totalRatings INT PATH 'lax $.rating.count'
+ )
+ );
+
This example will extract the values from the title (name of item) key and the nested field count (total number of ratings) key in the ratings array. and then place them into a table with the column names name and totalRatings.
| Name | Rating |
|---|---|
| Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops | 120 |
| Mens Casual Premium Slim Fit T-Shirts | 259 |
| Mens Cotton Jacket | 500 |
| Mens Casual Slim Fit | 430 |
| John Hardy Womenās Legends Naga Gold & Silver Dragon Station Chain Bracelet | 400 |
| Solid Gold Petite Micropave | 70 |
| White Gold Plated Princess | 400 |
| Pierced Owl Rose Gold Plated Stainless Steel Double | 100 |
| WD 2TB Elements Portable External Hard Drive - USB 3.0 | 203 |
| SanDisk SSD PLUS 1TB Internal SSD - SATA III 6 Gb/s | 470 |
The next example is sending a POST request to the https://fakestoreapi.com/users endpoint to create a new user. The fakeStoreApi docs indicate that the body of our HTTP POST request should contain the following JSON object:
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
{
+ "email":"John@gmail.com",
+ "username":"johnd",
+ "password":"m38rmF$",
+ "name":{
+ "firstname":"John",
+ "lastname":"Doe"
+ },
+ "address":{
+ "city":"kilcoole",
+ "street":"7835 new road",
+ "number":3,
+ "zipcode":"12926-3874",
+ "geolocation":{
+ "lat":"-37.3159",
+ "long":"81.1496"
+ }
+ },
+ "phone": "1-570-236-7033"
+}
+
Upon a successful add of a new user the API will return a 200 response code and a JSON object with the userās new id:
1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+
{
+ "address": {
+ "geolocation": {
+ "lat": "-37.3159",
+ "long": "81.1496"
+ },
+ "city": "kilcoole",
+ "street": "7835 new road"
+ },
+ "_id": "62c73539f0321700139f4682",
+ "id": 1,
+ "email": "John@gmail.com",
+ "username": "johnd",
+ "password": "m38rmF$",
+ "phone": "1-570-236-7033"
+}
+
QSYS2.HTTP_POST takes three This time arguments the URL, the HTTP body and the HTTP header parameters. This time the URL and body arguments of the QSYS2.HTTP_POST will be assigned to variables for readability.
We also need to specify the āContent-Typeā in the HTTP header to indicate that our HTTP body will be in JSON format. By default QSYS2.HTTP_POST specifies the content type of the body to be XML. To override this setting we pass in the header settings in JSON format:
1
+
{"header":"Content-Type,application/json;charset=utf-8"}
+
More information about the different header settings that can to passed to the
QSYS2.HTTP_XXXXtools can be found in the IBM docs
Here all the moving parts put together:
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
+
Create or replace variable @userURL varchar(50) ;
+SET @userURL = 'http://fakestoreapi.com/users';
+
+Create or replace variable @postBody varchar(500) ;
+SET @postBody = '{
+ "email":"John@gmail.com",
+ "username":"johnd",
+ "password":"m38rmF$",
+ "name":{
+ "firstname":"John",
+ "lastname":"Doe"
+ },
+ "address":{
+ "city":"kilcoole",
+ "street":"7835 new road",
+ "number":3,
+ "zipcode":"12926-3874",
+ "geolocation":{
+ "lat":"-37.3159",
+ "long":"81.1496"
+ }
+ },
+ "phone": "1-570-236-7033"
+}';
+
+SELECT *
+FROM JSON_TABLE(
+ QSYS2.HTTP_POST(
+ @userURL,
+ @postBody,
+ '{"header":"Content-Type,application/json;charset=utf-8"}'
+ ),
+ '$' COLUMNS(
+ testID INT PATH 'lax $.id',
+ email VARCHAR(50) PATH 'lax $.email',
+ username VARCHAR(50) PATH 'lax $.username',
+ password VARCHAR(50) PATH 'lax $.password'
+ )
+);
+
And the result:
| TESTID | USERNAME | PASSWORD | |
|---|---|---|---|
| 1 | John@gmail.com | johnd | m38rmF$ |
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.
A new version of content is available.