ibm-information-center/dist/eclipse/plugins/i5OS.ic.apiref_5.4.0.1/apiexdefque.htm

1520 lines
52 KiB
HTML
Raw Normal View History

2024-04-02 14:02:31 +00:00
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="reference" />
<meta name="DC.Title" content="Examples: Defining queries" />
<meta name="abstract" content="This topic includes several examples that use the Query (QQQQRY) API." />
<meta name="description" content="This topic includes several examples that use the Query (QQQQRY) API." />
<meta name="DC.Relation" scheme="URI" content="apiexmp.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="apiexdefque" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Examples: Defining queries</title>
</head>
<body id="apiexdefque"><a name="apiexdefque"><!-- --></a>
<!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Examples: Defining queries</h1>
<div><p>This topic includes several examples that use the Query (QQQQRY)
API.</p>
<div class="section"><p>The examples define the following query functions:</p>
<ul><li>A simple query to perform ordering</li>
<li>A join query</li>
<li>A join query with selection grouping and ordering</li>
</ul>
<div class="p">The following QQAPI header (or include) file and the QQFUNCS qu<div class="note"><span class="notetitle">Note:</span> Read
the <a href="codedisclaimer.htm">Code license and disclaimer information</a> for important legal information.</div>
ery
code are used by all the examples. The example programs follow the QQAPI header
and QQFUNCS code.</div>
</div>
<div class="section"><h4 class="sectiontitle">QQAPI header</h4><pre>/********************************************************************/
#ifndef _QQAPIH
#define _QQAPIH
/*******************************************************************/
/*******************************************************************/
/* */
/* FUNCTION: Defines constants and structures for use */
/* with the QQQQRY API examples. */
/* */
/* LANGUAGE: ILE C */
/* */
/* APIs USED: None */
/* */
/*******************************************************************/
/*******************************************************************/
/* The following define will enable some debug procedures and code */
/* #define QQDEBUG */
/* Query Open options */
#define QO_INPUT 1
#define QO_OUTPUT 2
#define QO_UPDATE 4
#define QO_DELETE 8
/* simple defines */
#define ON 1
#define OFF 0
/* user defined limits - change as needed */
#define MAX_ORDERBY 20
/* max number of order by fields (8000 max)*/
#define MAX_JOINTESTS 20
/* max number of join tests (999 max)*/
#define MAX_GROUPBY 20
/* max number of order by fields (120 max)*/
/* storage sizes - increase if needed */
#define QDT_SIZE 6000
#define FORMAT_SIZE 5000
#define SELECT_SIZE 5000
#define AP_SIZE 65535 /* Initialize access plan size to 64K */
/* Required definitions - do NOT change, hard limits */
#define MAX_FILES 32 /* Maximum number of files in a query */
#define REQ_REL "01" /* Required value for release field */
#define REQ_VER "00" /* Required value for version field */
#define QFLD_SIZE 30 /* QQ API field size - see qqqqry.h */
/* define error code structure */
typedef struct
{
int bytes_provided;
int bytes_available;
char msgid[(7]);
char reserved;
char data[(512]);
} error_code;
/* define attribute record for QUSCUSAT API */
typedef _Packed struct
{
int numAttrs;
int key;
int length;
_Packed union {
long spaceSize; /* key = 1 */
char initialValue; /* key = 2 */
char autoExtend; /* key = 3 */
} data;
} QUSCUSAT_T;
/* define access plan structure */
typedef _Packed struct
{
_SPCPTR storagePtr;
long size;
char reserved[(28]);
} ACCPLN_T;
/* Function prototypes: */
void dumpPtr(char *, char *, int );
char *strcnv400(char *, int );
int strcpy400(char *, char *, int );
void initUFCB(QDBUFCB_T *, int , Qdb_Qddfmt_t *);
void initQDT(QDBQH_T *, char , int , int ,
char , int );
void initFile(QDBQFHDR_T *, char , char );
void initFormat(Qdb_Qddfmt_t *, char *);
void initSelection(QDBQS_T *);
void initOrderBy(QDBQKH_T *);
void initGroupBy(QDBQGH_T *);
void initJoin(QDBQJHDR_T *);
int addFile(QDBQFHDR_T *, QDBQN_T *,
char *, char *, char *, char *);
int getRecordFmt(Qdb_Qddfmt_t *, long,
char *, char *, char *);
long copyField(Qdb_Qddfmt_t *, char *, int ,
Qdb_Qddfmt_t *);
void setFieldUsage(Qdb_Qddfmt_t *, char *, char );
int addSelectField(QDBQS_T *, char *, int );
int addSelectLiteral(QDBQS_T *, void *, int );
int addSelectOperator(QDBQS_T *, char *);
int addOrderBy(QDBQKH_T *, QDBQKF_T *,
char *, int );
int addGroupBy(QDBQGH_T *, QDBQGF_T *,
char *, int );
int addJoinTest(QDBQJHDR_T *, QDBQJFLD_T *, char *,
int , char *, int , char *);
void addQDTsection(QDBQH_T *, char *, int , int *);
long createAccessPlanSpace(ACCPLN_T *, char *, long );
int saveQDT(QDBQH_T *, ACCPLN_T *);
int saveAccessPlan(ACCPLN_T *);
int loadQDT(QDBQH_T *, ACCPLN_T *);
long loadAccessPlan(ACCPLN_T *, char *);
#endif
/********************************************************************/</pre>
</div>
<div class="section"><h4 class="sectiontitle">QQFUNCS query code</h4><pre>/********************************************************************/
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;qdbrtvfd.h&gt;
#include &lt;qqqqry.h&gt;
#include &lt;quscrtus.h&gt;
#include &lt;qusptrus.h&gt;
#include &lt;quscusat.h&gt;
#include &lt;qusrusat.h&gt;
#include "qqapi.h"
/*******************************************************************/
/*******************************************************************/
/* */
/* FUNCTION: This module contains all of the functions */
/* used by the examples to build the API information. */
/* */
/* LANGUAGE: ILE C */
/* */
/* APIs USED: QDBRTVFD, QUSCRTUS, QUSCUSAT, QUSPTRUS, QUSRUSAT */
/* */
/*******************************************************************/
/*******************************************************************/
#ifdef QQDEBUG
/* dumpPtr(comment string, pointer, length)
- prints a comment then dumps data in hexadecimal starting at the
given pointer location for the specified length */
void dumpPtr(char *text, char *ptr, int len)
{
int i;
printf("%s\n", text);
for (i=0; i &lt; len; i++, ptr++)
{
printf("%02X ", (int) *ptr);
if ((i+1) % 16 == 0)
printf("\n");
}
printf("\n");
}
#endif
/* strcnv400(source string, string length)
- convert a string to a zero terminated string */
char *strcnv400(char *str, int len)
{
static char buffer[256];
strncpy(buffer, str, len);
buffer[len] = (char) 0;
return(buffer);
}
/* strcpy400(destination string, source string, source length)
- copy a zero terminated string to a string, pad with blanks
if necessary */
int strcpy400(char *dest, char *src, int len)
{
int i;
if ((i = strlen(src)) &gt; len)
len = i;
if (len)
memcpy(dest, src, strlen(src));
if (i &lt; len)
memset((dest+i), ' ', len-i);
return(len);
}
/* initUFCB(ufcb, open options, record format)
- initialize the UFCB structure */
void initUFCB(QDBUFCB_T *ufcbPtr, int openFlags,
Qdb_Qddfmt_t *formatPtr)
{
_Packed struct qufcb *ufcb;
/* verify parameters */
if (ufcbPtr == NULL || openFlags == 0)
{
printf("Invalid UFCB settings\n");
return;
}
/* Clear the entire UFCB */
memset((void *) ufcbPtr, (char) 0, sizeof(QDBUFCB_T));
/* Now start initializing values */
ufcb = &amp;ufcbPtr-&amp;gt;qufcb;
strcpy400((char *) ufcb-&gt;relver.release, REQ_REL,
sizeof(ufcb-&gt;relver.release));
strcpy400((char *) ufcb-&gt;relver.version, REQ_VER,
sizeof(ufcb-&gt;relver.version));
/* Blocked Records (BLKRCD) should be on if CPYFRMQRYF is used */
ufcb-&gt;markcnt.flg2brcd = ON;
ufcb-&gt;parameter.maximum = MAXFORMATS;
/* Set the open option */
if (openFlags&amp;QO_INPUT)
ufcb-&gt;open.flagui = ON;
if (openFlags&amp;QO_OUTPUT)
ufcb-&gt;open.flaguo = ON;
if (openFlags&amp;QO_UPDATE)
ufcb-&gt;open.flaguu = ON;
if (openFlags&amp;QO_DELETE)
ufcb-&gt;open.flagud = ON;
/* set up options to match _Ropen options */
ufcb-&gt;parameter.keyfdbk = KEYFDBK;
ufcb-&gt;parameter.keyonoff = ON; /* Key feedback ON */
ufcb-&gt;parameter.filedep = FILEDEP;
ufcb-&gt;parameter.fldonoff = ON; /* File dependent I/O ON */
/* turn the rest of the parameters off */
ufcb-&gt;parameter.seqonly = NOTSEQUPROC;
ufcb-&gt;parameter.primrln1 = NOTRECORDLTH;
ufcb-&gt;parameter.commitc = NOTCOMITCTL;
/* if the format is supplied,
define it in the UFCB and do level checking */
if (formatPtr != NULL)
{
ufcb-&gt;parameter.lvlchk = LEVELCK;
ufcb-&gt;parameter.lvlonoff = ON; /* Level check ON */
ufcb-&gt;parameter.curnum = 1; /* only one format */
/* set the format name and format level identifier */
ufcb-&gt;parameter.recfmts = FORMATSEQ;
memcpy(ufcb-&gt;parameter.formats[0].name, formatPtr-&gt;Qddfname,
sizeof(ufcb-&gt;parameter.formats[0].name));
memcpy(ufcb-&gt;parameter.formats[0].number, formatPtr-&gt;Qddfseq,
sizeof(ufcb-&gt;parameter.formats[0].number));
}
else /* no format and level checking */
{
ufcb-&gt;parameter.lvlchk = NOTLEVELCK;
ufcb-&gt;parameter.recfmts = NOTFORMATSEQ;
}
ufcb-&gt;ufcbend = ENDLIST;
}
/* initQDT(qdt, options...)
- initialize the QDT header */
void initQDT(QDBQH_T *qdtHdr, char alwCpyDta,
int optAllAp, int statusMsgs,
char optimize, int forRows)
{
if (qdtHdr == NULL)
{
printf("Invalid QDT settings\n");
return; /* invalid pointer */
}
/* Clear the entire QDT */
memset((void *) qdtHdr, (char) 0, sizeof(QDBQH_T));
/* set the initial QDT space used size */
qdtHdr-&gt;qdbspcsize = sizeof(QDBQH_T);
/* QDT options... */
/* ordering not specified */
qdtHdr-&gt;qdbqkeyo = -1;
/* set optimize parameter (ALLIO, FIRSTIO, MINWAIT) */
if (optimize == QDBQFINA || optimize == QDBQFINF ||
optimize == QDBQFINM || optimize == QDBQFINC)
qdtHdr-&gt;qdbqfin = optimize; /* OPTIMIZE() parameter */
else
qdtHdr-&gt;qdbqfin = QDBQFINA; /* default to OPTIMIZE(*ALLIO) */
/* set allow copy data parameter (YES, NO, OPTIMIZE) */
if (alwCpyDta == QDBQTEMN || alwCpyDta == QDBQTEMO ||
alwCpyDta == QDBQTEMA)
qdtHdr-&gt;qdbqtem = alwCpyDta; /* ALWCPYDTA() parameter */
else
qdtHdr-&gt;qdbqtem = QDBQTEMA; /* default to ALWCPYDTA(*YES) */
/* status messages (YES, NO) */
qdtHdr-&gt;qdbqattr.qdbqnst = statusMsgs ? ON : OFF;
/* optimize all access path parameter (YES, NO) */
qdtHdr-&gt;qdbqdt_7.qdbqopta = optAllAp ? ON : OFF;
/* optimizer for n rows parameter */
qdtHdr-&gt;qdbq_optmrows = forRows &gt; 0 ? forRows : 0;
}
/* initFile(file section, join type, join order option)
- initialize the file header section */
void initFile(QDBQFHDR_T *fileHdr, char joinType, char joinOrder)
{
if (fileHdr == NULL)
{
printf("Invalid File Header settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) fileHdr, (char) 0, sizeof(QDBQFHDR_T));
/* File Spec options... */
/* inner, partial outer or exception join type */
if (joinType == QDBQINNJ || joinType == QDBQOUTJ ||
joinType == QDBQEXCJ)
fileHdr-&gt;qdbqmfop = joinType;
else
fileHdr-&gt;qdbqmfop = QDBQINNJ;
/* join order - any order or join as specified */
fileHdr-&gt;qdbqmfor = joinOrder == QDBQMFON ? QDBQMFON : QDBQMFOA;
}
/* initFormat(format section, format name)
- initialize the format header section */
void initFormat(Qdb_Qddfmt_t *formatHdr, char *name)
{
if (formatHdr == NULL)
{
printf("Invalid Format Header settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) formatHdr, (char) 0, sizeof(Qdb_Qddfmt_t));
/* Format Spec options... */
strcpy400(formatHdr-&gt;Qddfname, name, sizeof(formatHdr-&gt;Qddfname));
formatHdr-&gt;Qddfrcid = 65535;
formatHdr-&gt;Qddfsrcd = 65535;
formatHdr-&gt;Qddflgs.Qddfrsid = 1;
memset(formatHdr-&gt;Qddfseq, ' ', sizeof(formatHdr-&gt;Qddfseq));
memset(formatHdr-&gt;Qddftext, ' ', sizeof(formatHdr-&gt;Qddftext));
/* Format size (so far) */
formatHdr-&gt;Qddbyava = sizeof(Qdb_Qddfmt_t);
formatHdr-&gt;Qddbyrtn = formatHdr-&gt;Qddbyava;
}
/* initSelection(selection section)
- initialize the selection header section */
void initSelection(QDBQS_T *selectHdr)
{
if (selectHdr == NULL)
{
printf("Invalid selection settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) selectHdr, (char) 0, sizeof(QDBQS_T));
/* set initial selection spec size (minus dummy selection spec) */
selectHdr-&gt;qdbqsl = sizeof(QDBQS_T) - sizeof(selectHdr-&gt;qdbqspec);
}
/* initOrderBy(orderby section)
- initialize order by header section */
void initOrderBy(QDBQKH_T *orderByHdr)
{
if (orderByHdr == NULL)
{
printf("Invalid Order By settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) orderByHdr, (char) 0, sizeof(QDBQKH_T));
}
/* initGroupBy(groupby section)
- initialize group by header section */
void initGroupBy(QDBQGH_T *groupByHdr)
{
if (groupByHdr == NULL)
{
printf("Invalid Group By settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) groupByHdr, (char) 0, sizeof(QDBQGH_T));
}
/* initJoin(join section)
- initialize join header section */
void initJoin(QDBQJHDR_T *joinHdr)
{
if (joinHdr == NULL)
{
printf("Invalid Join settings\n");
return; /* invalid pointer */
}
/* Clear the header */
memset((void *) joinHdr, (char) 0, sizeof(QDBQKH_T));
/* set initial join spec size */
joinHdr-&gt;qdbqjln = sizeof(QDBQJHDR_T);
}
/* addFile (file section, file spec section, file name, file library,
file member, file format)
- add file information to the file section */
int addFile(QDBQFHDR_T *fileHdr, QDBQN_T *fileSpec,
char *filename, char *library, char *member, char *format)
{
int i;
QDBQFLMF_T *fileSpecPtr;
if (fileHdr == NULL || fileSpec == NULL || filename == NULL)
return(0); /* invalid data */
if (fileHdr-&gt;qdbqfilnum == MAX_FILES)
return(0); /* no more files allowed */
/* increment the count of file specs */
i = fileHdr-&gt;qdbqfilnum++;
/* initialize the file spec area */
memset((void *) &amp;fileSpec[i], (char) 0, sizeof(QDBQN_T));
fileSpecPtr = (QDBQFLMF_T *) &amp;fileSpec[i].qdbqflmf;
/* fill in the data... */
strcpy400(fileSpecPtr-&gt;qdbqfile, filename,
sizeof(fileSpecPtr-&gt;qdbqfile));
if (library == NULL)
strcpy400(fileSpecPtr-&gt;qdbqlib, QDBQLIBL,
sizeof(fileSpecPtr-&gt;qdbqlib));
else
strcpy400(fileSpecPtr-&gt;qdbqlib, library,
sizeof(fileSpecPtr-&gt;qdbqlib));
if (member == NULL)
strcpy400(fileSpecPtr-&gt;qdbqmbr, QDBQFRST,
sizeof(fileSpecPtr-&gt;qdbqmbr));
else
strcpy400(fileSpecPtr-&gt;qdbqmbr, member,
sizeof(fileSpecPtr-&gt;qdbqmbr));
if (format == NULL)
strcpy400(fileSpecPtr-&gt;qdbqfmt, QDBQONLY,
sizeof(fileSpecPtr-&gt;qdbqfmt));
else
strcpy400(fileSpecPtr-&gt;qdbqfmt, format,
sizeof(fileSpecPtr-&gt;qdbqfmt));
/* return the amount of storage used in the file specs */
return(fileHdr-&gt;qdbqfilnum*sizeof(QDBQN_T));
}
/* getRecordFmt(format, format storage size(max),
file name, file library, file format)
- get a record format (using QDBRTVFD) */
int getRecordFmt(Qdb_Qddfmt_t *formatPtr, long spaceSize,
char *filename, char *libname, char *formatname)
{
error_code errcod;
char override = '1'; /* process overrides */
char fileLibname[20];
char outFilLib[20];
char format[10];
if (formatPtr == NULL || filename == NULL)
return(0); /* missing data */
errcod.bytes_provided = 512;
errcod.msgid[0] = (char) 0;
/* set up temporary variables... */
strcpy400(fileLibname, filename, 10);
if (libname == NULL)
strcpy400(&amp;fileLibname[10], QDBQLIBL, 10);
else
strcpy400(&amp;fileLibname[10], libname, 10);
if (formatname == NULL)
strcpy400(format, filename, 10);
else
strcpy400(format, formatname, 10);
/* call the RTVFD API to get the record format */
QDBRTVFD((char *) formatPtr, spaceSize, outFilLib,
"FILD0200",
fileLibname, format, &amp;override,
"*LCL ", "*EXT ", &amp;errcod);
if (errcod.msgid[0])
{
printf("API QDBRTVFD failed\n");
printf("msgid = %7s\n", strcnv400(errcod.msgid,
sizeof(errcod.msgid)));
}
if (formatPtr-&gt;Qddbyrtn != formatPtr-&gt;Qddbyava)
return(0); /* missing data */
/* return total storage used in format */
return(formatPtr-&gt;Qddbyrtn);
}
/* copyField(format, field name, file number, existing format)
- copy a field from an existing format */
long copyField(Qdb_Qddfmt_t *formatPtr, char *fieldName, int fieldFile,
Qdb_Qddfmt_t *oldFormatPtr)
{
int i;
long fieldSize;
char padField[30];
Qdb_Qddffld_t *fieldPtr, *oldFieldPtr;
if (formatPtr == NULL || fieldName == NULL || oldFormatPtr == NULL)
return(0); /* missing data */
strcpy400(padField, fieldName, 30);
/* set up field pointers */
fieldPtr = (Qdb_Qddffld_t *) ((char *) formatPtr +
formatPtr-&gt;Qddbyava);
oldFieldPtr = (Qdb_Qddffld_t *) (oldFormatPtr + 1);
/* loop through all the fields, looking for a match */
for (i=0; i &lt; oldFormatPtr-&gt;Qddffldnum; i++,
oldFieldPtr = (Qdb_Qddffld_t *) ((char *) oldFieldPtr +
oldFieldPtr-&gt;Qddfdefl))
/* if a match was found... */
if (memcmp(oldFieldPtr-&gt;Qddfflde, padField, 30) == 0)
{
/* copy the field over */
fieldSize = oldFieldPtr-&gt;Qddfdefl;
memcpy(fieldPtr, oldFieldPtr, fieldSize);
/* set the file number it was defined in */
fieldPtr-&gt;Qddfjref = fieldFile;
/* increment the format header information */
formatPtr-&gt;Qddffldnum++;
formatPtr-&gt;Qddfrlen += fieldPtr-&gt;Qddffldb;
formatPtr-&gt;Qddbyava += fieldSize;
formatPtr-&gt;Qddbyrtn = formatPtr-&gt;Qddbyava;
break;
}
/* return total storage used in format */
return(formatPtr-&gt;Qddbyrtn);
}
/* setFieldUsage(format, field name, usage)
- set the field usage in a format */
void setFieldUsage(Qdb_Qddfmt_t *formatPtr, char *fieldName, char usage)
{
int i;
char padField[30];
Qdb_Qddffld_t *fieldPtr;
if (formatPtr == NULL)
return; /* missing data */
if (fieldName != NULL)
strcpy400(padField, fieldName, 30);
/* set up field pointers */
fieldPtr = (Qdb_Qddffld_t *) (formatPtr + 1);
/* loop through all the fields, looking for a match */
for (i=0; i &lt; formatPtr-&gt;Qddffldnum; i++,
fieldPtr = (Qdb_Qddffld_t *) ((char *) fieldPtr +
fieldPtr-&gt;Qddfdefl))
/* if all fields to be set or a match was found... */
if (fieldName == NULL ||
memcmp(fieldPtr-&gt;Qddfflde, padField, 30) == 0)
fieldPtr-&gt;Qddffiob = usage;
}
/* addSelectField(section section, field name, file number for field)
- add a selection for a file field to the selection section */
int addSelectField(QDBQS_T *selectHdr, char *fieldName, int fieldFile)
{
QDBQSIT_T *selectItemPtr;
QDBQSOPF_T *selectFldPtr;
int itemSize;
if (selectHdr == NULL || fieldName == NULL)
return(0); /* invalid data */
/* set up all the section for adding a field */
selectItemPtr = (QDBQSIT_T *) ((char *) selectHdr +
selectHdr-&gt;qdbqsl);
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr-&gt;qdbqsitm);
memset((void *) selectItemPtr, (char) 0, itemSize);
selectFldPtr = (QDBQSOPF_T *) ((char *) selectItemPtr + itemSize);
memset((void *) selectFldPtr, (char) 0, sizeof(QDBQSOPF_T));
/* set up the selection item information for a field */
selectItemPtr-&gt;qdbqslen = itemSize + sizeof(QDBQSOPF_T);
/* length */
selectItemPtr-&gt;qdbqsitt = QDBQOPF; /* type is field */
/* now set up the field */
strcpy400(selectFldPtr-&gt;qdbqsofn, fieldName,
sizeof(selectFldPtr-&gt;qdbqsofn));
selectFldPtr-&gt;qdbqsofj = fieldFile;
/* update the header statistics */
selectHdr-&gt;qdbqsnum++; /* increment number of select specs */
selectHdr-&gt;qdbqsl += selectItemPtr-&gt;qdbqslen; /* total length */
/* return the total storage now in the selection section */
return(selectHdr-&gt;qdbqsl);
}
/* addSelectLiteral(selection section, literal, size of literal data)
- add a selection for a literal to the selection section */
int addSelectLiteral(QDBQS_T *selectHdr, void *literal, int sizeLit)
{
QDBQSIT_T *selectItemPtr;
QDBQSOCH_T *selectLitPtr;
void *selectDataPtr;
int itemSize;
if (selectHdr == NULL || literal == NULL || sizeLit &lt; 1)
return(0); /* invalid data */
/* set up all the sections for adding a literal */
selectItemPtr = (QDBQSIT_T *)
((char *) selectHdr + selectHdr-&gt;qdbqsl);
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr-&gt;qdbqsitm);
memset((void *) selectItemPtr, (char) 0, itemSize);
selectLitPtr = (QDBQSOCH_T *) ((char *) selectItemPtr + itemSize);
memset((void *) selectLitPtr, (char) 0, sizeof(QDBQSOCH_T));
selectDataPtr = (void *) (selectLitPtr + 1);
/* set up the selection item information for a literal */
selectItemPtr-&gt;qdbqslen = itemSize + sizeof(QDBQSOCH_T) + sizeLit;
selectItemPtr-&gt;qdbqsitt = QDBQOPC; /* literal type */
/* now set up the literal */
selectLitPtr-&gt;qdbqsocl = sizeLit; /* literal size */
selectLitPtr-&gt;qdbqsoft = '\xFF';
/* use job format for date/time fields */
memcpy(selectDataPtr, literal, sizeLit);
/* save the literal value */
/* update the header statistics */
selectHdr-&gt;qdbqsnum++; /* increment number of select specs */
selectHdr-&gt;qdbqsl += selectItemPtr-&gt;qdbqslen; /* total length */
/* return the total storage now in the selection section */
return(selectHdr-&gt;qdbqsl);
}
/* addSelectOperator(selection section, operator type)
- add a selection for an operator to the selection section */
int addSelectOperator(QDBQS_T *selectHdr, char *operator)
{
QDBQSIT_T *selectItemPtr;
QDBQSOPR_T *selectOprPtr;
QDBQSOP2_T *selectWldPtr;
int itemSize;
int oprSize;
if (selectHdr == NULL || operator == NULL)
return(0); /* invalid data */
/* set up all the sections for adding an operator */
selectItemPtr = (QDBQSIT_T *)
((char *) selectHdr + selectHdr-&gt;qdbqsl);
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr-&gt;qdbqsitm);
memset((void *) selectItemPtr, (char) 0, itemSize);
selectOprPtr = (QDBQSOPR_T *) ((char *) selectItemPtr + itemSize);
oprSize = sizeof(QDBQSOPR_T) + sizeof(QDBQSOP2_T);
memset((void *) selectOprPtr, (char) 0, oprSize);
/* set up the selection item information for an operator */
selectItemPtr-&gt;qdbqslen = itemSize + oprSize; /* length */
selectItemPtr-&gt;qdbqsitt = QDBQOPTR; /* operator type */
/* now set up the operator */
memcpy(selectOprPtr-&gt;qdbqsop, operator,
sizeof(selectOprPtr-&gt;qdbqsop));
/* wildcard operator set up */
if (memcmp(operator, QDBQWILD, 2) == 0)
{
selectOprPtr-&gt;qdbqswc1 = '_';
selectOprPtr-&gt;qdbqswc2 = '*';
selectWldPtr = (QDBQSOP2_T *) (selectOprPtr + 1);
memcpy(selectWldPtr-&gt;qdbqsdb1,"\42_", 2);
memcpy(selectWldPtr-&gt;qdbqsdb2,"\42*", 2);
}
/* update the header statistics */
selectHdr-&gt;qdbqsnum++; /* increment number of select specs */
selectHdr-&gt;qdbqsl += selectItemPtr-&gt;qdbqslen; /* total length */
/* return the total storage now in the selection section */
return(selectHdr-&gt;qdbqsl);
}
/* addOrderBy(orderby section, orderby specs section, key field name,
descend sort option
- add an order by to the order by section */
int addOrderBy(QDBQKH_T *orderByHdr, QDBQKF_T *orderByFld,
char *keyfield, int descend)
{
int i;
QDBQKF_T *orderByFldPtr;
if (orderByHdr == NULL || orderByFld == NULL || keyfield == NULL)
return(0);
if (orderByHdr-&gt;qdbqknum == MAX_ORDERBY)
return(0);
/* increment the order by spec counter */
i = orderByHdr-&gt;qdbqknum++;
/* add the new orderby data */
orderByFldPtr = &amp;orderByFld[i];
memset((void *) orderByFldPtr, (char) 0, sizeof(QDBQKF_T));
strcpy400(orderByFldPtr-&gt;qdbqkfld, keyfield,
sizeof(orderByFldPtr-&gt;qdbqkfld));
orderByFldPtr-&gt;qdbqksq.qdbqksad = (descend) ? ON : OFF;
/* return the space used by the order by specs */
return(orderByHdr-&gt;qdbqknum*sizeof(QDBQKF_T));
}
/* addGroupBy(groupby section, groupby field spec section,
groupby field name, file number of groupby field)
- add a group by to the group by section */
int addGroupBy(QDBQGH_T *groupByHdr, QDBQGF_T *groupByFld,
char *groupfield, int fromFile)
{
int i;
QDBQGF_T *groupByFldPtr;
if (groupByHdr == NULL || groupByFld == NULL || groupfield == NULL)
return(0);
if (groupByHdr-&gt;qdbqgfnum == MAX_GROUPBY)
return(0);
/* increment the group by spec counter */
i = groupByHdr-&gt;qdbqgfnum++;
/* add the new groupby data */
groupByFldPtr = (QDBQGF_T *) &amp;groupByFld[i];
memset((void *) groupByFldPtr, (char) 0, sizeof(QDBQGF_T));
strcpy400(groupByFldPtr-&gt;qdbqgfld, groupfield,
sizeof(groupByFldPtr-&gt;qdbqgfld));
groupByFldPtr-&gt;qdbqgflj = fromFile;
/* return the space used by the group by specs */
return(groupByHdr-&gt;qdbqgfnum*sizeof(QDBQGF_T));
}
/* addJoinTest(join section, join test section, join from field name,
join from file number, join to field name, join to file number,
join operator)
- add a join test to the join section */
int addJoinTest(QDBQJHDR_T *joinHdr,
QDBQJFLD_T *joinSpec, char *fromFld,
int fromFile, char *toFld, int toFile, char *joinOp)
{
int i;
QDBQJFLD_T *joinSpecPtr;
if (joinHdr == NULL || joinSpec == NULL)
return(0);
if (joinHdr-&gt;qdbqjknum == MAX_JOINTESTS)
return(0);
/* increment the join test counter */
i = joinHdr-&gt;qdbqjknum++;
memset((void *) &amp;joinSpec[i], (char) 0, sizeof(QDBQJFLD_T));
/* add the new join data */
joinSpecPtr = &amp;joinSpec[i];
strcpy400(joinSpecPtr-&gt;qdbqjfnm, fromFld,
sizeof(joinSpecPtr-&gt;qdbqjfnm));
joinSpecPtr-&gt;qdbqjfnum = fromFile; /* 1, 2, 3, etc */
strcpy400(joinSpecPtr-&gt;qdbqjtnm, toFld,
sizeof(joinSpecPtr-&gt;qdbqjtnm));
joinSpecPtr-&gt;qdbqjtnum = toFile; /* 1, 2, 3, etc */
/* Join operator - see #defines in QQ API include */
strcpy400(joinSpecPtr-&gt;qdbqjop, joinOp,
sizeof(joinSpecPtr-&gt;qdbqjop));
/* set size of entire join spec */
joinHdr-&gt;qdbqjln += sizeof(QDBQJFLD_T);
/* return the space used by the join tests */
return(joinHdr-&gt;qdbqjknum*sizeof(QDBQJFLD_T));
}
/* addQDTsection(qdt, new section, size of new section, qdt offset)
- place a new section into the QDT */
void addQDTsection(QDBQH_T *qdtHdr, char *newSection,
int newSize, int *offset)
{
char *sectionPtr;
/* position to the current end of the QDT */
sectionPtr = (char *) qdtHdr + qdtHdr-&gt;qdbspcsize;
/* append in the new section data */
memcpy(sectionPtr, newSection, newSize);
/* if an offset is to be stored, remember it now */
if (offset != NULL)
*offset = qdtHdr-&gt;qdbspcsize;
/* update the QDT size */
qdtHdr-&gt;qdbspcsize += newSize;
}
/* createAccessPlanSpace(access plan, user space name, size)
- creates a *USRSPC object for storing the access plan */
long createAccessPlanSpace(ACCPLN_T *accessPlan, char *name,
long spaceSize)
{
QUSCUSAT_T chgAttr;
_SPCPTR usrSpcPtr;
char library[10];
char value = (char) 0;
char text[50];
error_code errcode;
errcode.bytes_provided = 512;
strcpy400(text,"Access Plan for QQ API example",50);
/* Create the User Space */
QUSCRTUS(name,
"ACCESSPLAN",
spaceSize,
&amp;value,
"*ALL ",
text,
"*YES ",
&amp;errcode,
"*USER ");
if (errcode.msgid[0])
{
printf("Create User Space API failed!\n");
printf("msgid = %7s\n", strcnv400(errcode.msgid,
sizeof(errcode.msgid)));
return(-1);
}
/* Change the User Space to allow Auto-Extend */
strcpy400(library,&amp;name[10],10);
chgAttr.numAttrs = 1;
chgAttr.key = 3; /* Auto extend */
chgAttr.length = sizeof(char);
chgAttr.data.autoExtend = '1';
QUSCUSAT(library,
name,
&amp;chgAttr,
&amp;errcode);
if (errcode.msgid[0])
{
printf("Change User Space Attributes FAILED!\n");
printf("msgid = %7s\n", strcnv400(errcode.msgid,
sizeof(errcode.msgid)));
return(-1);
}
/* Retrieve Space Pointer to the User Space */
QUSPTRUS(name,
&amp;usrSpcPtr,
&amp;errcode);
if (errcode.msgid[0])
{
printf("Retrieve Space Pointer to User Space FAILED!\n");
printf("msgid = %7s\n", strcnv400(errcode.msgid,
sizeof(errcode.msgid)));
return(-1);
}
/* Now move to the access plan itself (on 16 byte boundary) */
accessPlan-&gt;storagePtr = (_SPCPTR) ((char*) usrSpcPtr + 16);
return(0);
}
/* saveAccessPlan(access plan)
- update the size in the access plan (QQQQRY actually wrote the data) */
int saveAccessPlan(ACCPLN_T *accessPlan)
{
_SPCPTR usrSpcPtr;
/* Position to the start of the user space */
usrSpcPtr = (_SPCPTR) ((char*) accessPlan-&gt;storagePtr - 16);
/* Write the access plan size out at the start */
memcpy(usrSpcPtr, (void *) &amp;accessPlan-&gt;size,
sizeof(accessPlan-&gt;size));
#ifdef QQDEBUG
printf("AP size = %ld\n", accessPlan-&gt;size);
#endif
return(0);
}
/* saveQDT(qdt, access plan)
- append the QDT to the end of the access plan */
int saveQDT(QDBQH_T *qdtPtr, ACCPLN_T *accessPlan)
{
_SPCPTR usrSpcPtr;
/* Position to the just after the access plan */
usrSpcPtr = (_SPCPTR) ((char*) accessPlan-&gt;storagePtr +
accessPlan-&gt;size);
/* Write the QDT size out */
memcpy(usrSpcPtr, &amp;qdtPtr-&gt;qdbspcsize, sizeof(qdtPtr-&gt;qdbspcsize));
#ifdef QQDEBUG
printf("qdt size = %ld\n", qdtPtr-&gt;qdbspcsize);
#endif
/* Move up the user space pointer */
usrSpcPtr = (_SPCPTR) ((char *) usrSpcPtr + 16);
/* Write the QDT itself out */
memcpy(usrSpcPtr, qdtPtr, qdtPtr-&gt;qdbspcsize);
return(0);
}
/* loadQDT(qdt, access plan)
- load the QDT from the end of the access plan */
int loadQDT(QDBQH_T *qdtPtr, ACCPLN_T *accessPlan)
{
_SPCPTR usrSpcPtr;
/* Position to the just after the access plan */
usrSpcPtr = (_SPCPTR) ((char*) accessPlan-&gt;storagePtr +
accessPlan-&gt;size);
/* Write the QDT size out */
memcpy((void *) &amp;qdtPtr-&gt;qdbspcsize, usrSpcPtr,
sizeof(qdtPtr-&gt;qdbspcsize));
#ifdef QQDEBUG
printf("qdt size = %ld\n", qdtPtr-&gt;qdbspcsize);
#endif
/* Move up the user space pointer */
usrSpcPtr = (_SPCPTR) ((char *) usrSpcPtr + 16);
/* Write the QDT itself out */
memcpy((void *) qdtPtr, usrSpcPtr, qdtPtr-&gt;qdbspcsize);
return(qdtPtr-&gt;qdbspcsize);
}
/* loadAccessPlan(access plan, userspace name)
- loads an access plan from a *USRSPC object */
long loadAccessPlan(ACCPLN_T *accessPlan, char *name)
{
Qus_SPCA_0100_t usrSpcAttr;
_SPCPTR usrSpcPtr;
error_code errcode;
errcode.bytes_provided = 512;
errcode.msgid[0] = (char) 0;
/* Retrieve Space Pointer to the User Space */
QUSPTRUS(name, &amp;usrSpcPtr, &amp;errcode);
if (errcode.msgid[0])
{
printf("Retrieve Space Pointer to User Space FAILED!\n");
printf("msgid = %7s\n", strcnv400(errcode.msgid,
sizeof(errcode.msgid)));
return(0);
}
/* Retrieve Size of Access Plan */
QUSRUSAT(&amp;usrSpcAttr,
sizeof(Qus_SPCA_0100_t),
"SPCA0100",
name,
&amp;errcode);
if (errcode.msgid[0])
{
printf("Retrieve User Space Attributes FAILED!\n");
printf("msgid = %7s\n", strcnv400(errcode.msgid,
sizeof(errcode.msgid)));
return(0);
}
#ifdef QQDEBUG
else
{
printf("Original User Space Attributes\n");
printf("Bytes Returned ==&gt; %d\n",usrSpcAttr.Bytes_Returned);
printf("Bytes Available ==&gt; %d\n",usrSpcAttr.Bytes_Available);
printf("Space Size ==&gt; %d\n",usrSpcAttr.Space_Size);
printf("Auto Extend ==&gt; %c\n",
usrSpcAttr.Automatic_Extendability);
}
#endif
/* Pull the access plan size out first */
memcpy((void *) &amp;accessPlan-&gt;size, usrSpcPtr,
sizeof(accessPlan-&gt;size));
#ifdef QQDEBUG
printf("AP size = %ld\n", accessPlan-&gt;size);
#endif
/* Now move to the access plan itself (on 16 byte boundary) */
accessPlan-&gt;storagePtr = (_SPCPTR) ((char*) usrSpcPtr + 16);
return(accessPlan-&gt;size);
}
/********************************************************************/</pre>
</div>
<div class="section"><h4 class="sectiontitle">Defining a simple query</h4><p>This QQQQRY API example
defines a simple query to perform ordering. The following is the equivalent
SQL:</p>
<pre>SELECT * FROM OPENFILE1
ORDER BY LNAME</pre>
<pre>/********************************************************************/
/* PROGRAM: QQAPI1 */
/* */
/* LANGUAGE: ILE C */
/* */
/* DESCRIPTION: THIS PROGRAM DEFINES A SIMPLE QUERY TO PERFORM */
/* ORDERING. */
/* */
/* APIs USED: QQQQRY */
/* */
/********************************************************************/
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;recio.h&gt;
#include &lt;qdbrtvfd.h&gt;
#include &lt;qqqqry.h&gt;
#include "qqapi.h"
/* get the record format from the file */
#pragma mapinc("recfmt","APIQQ/OPENFILE1(OPENFILE1)","input","p z",,)
#include "recfmt"
/* main - start of the program
*
* Flow:
* - initialize variables
* - override to set up sharing
* - build various QDT sections
* - build QDT with those sections
* - QQQQRY to run the query
* - open the data path
* - read the data and display it
* - close the data paths
*
*/
main()
{
/* record I/O variables */
_RIOFB_T *feedback;
_RFILE *file1;
APIQQ_OPENFILE1_OPENFILE1_i_t recBuf;
int recCount = 0;
/* Query variables */
QDBUFCB_T ufcbBuf;
char qdtBuf[QDT_SIZE];
char formatBuf[FORMAT_SIZE];
QDBQH_T *qdtPtr;
Qdb_Qddfmt_t *formatPtr;
QDBQFHDR_T fileHdr;
QDBQN_T fileSpec[MAX_FILES];
QDBQKH_T orderByHdr;
QDBQKF_T orderByFld[MAX_ORDERBY];
int formatSize;
int fileSpecSize;
int orderBySize;
error_code errcod;
errcod.bytes_provided = 512;
/* initialize the pointers */
qdtPtr = (QDBQH_T *) qdtBuf;
formatPtr = (Qdb_Qddfmt_t *) formatBuf;
/* initialize the headers */
initQDT(qdtPtr, QDBQTEMO, ON, ON, QDBQFINA, 0);
initFile(&amp;fileHdr, QDBQINNJ, QDBQMFOA);
initOrderBy(&amp;orderByHdr);
/* set up override to allow sharing */
system("OVRDBF FILE(OPENFILE1) SHARE(*YES)");
/* Note: If level checking is not done
(ie. no format on initUFCB) then
the override above must specify LVLCHK(*NO) */
/* build the individual QDT sections */
fileSpecSize = addFile(&amp;fileHdr, fileSpec, "OPENFILE1",
NULL, NULL, NULL);
formatSize = getRecordFmt(formatPtr, FORMAT_SIZE, "OPENFILE1",
NULL, NULL);
orderBySize = addOrderBy(&amp;orderByHdr, orderByFld, "LNAME", OFF);
/* initialize the UFCB */
initUFCB(&amp;ufcbBuf, QO_INPUT, formatPtr);
/* Now build the real QDT... */
addQDTsection(qdtPtr, (char *) &amp;fileHdr,
sizeof(fileHdr), &amp;qdtPtr-&gt;qdbqfilo);
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
addQDTsection(qdtPtr, (char *) formatPtr,
formatSize, &amp;qdtPtr-&gt;qdbqfldo);
addQDTsection(qdtPtr, (char *) &amp;orderByHdr, sizeof(orderByHdr),
&amp;qdtPtr-&gt;qdbqkeyo);
addQDTsection(qdtPtr, (char *) orderByFld, orderBySize, NULL);
/* Finally, run the query! */
QQQQRY("RUNQRY ", (char *) &amp;ufcbBuf, qdtBuf, NULL, NULL,
&amp;errcod);
if (errcod.msgid[0])
{
printf("API QQQQRY failed\n");
printf("msgid = %7s\n", strcnv400(errcod.msgid,
sizeof(errcod.msgid)));
}
/* Now access the data */
if ((file1 = _Ropen("OPENFILE1", "rr riofb=N")) == NULL)
{
printf("Error opening file\n");
exit(1);
}
/* Perform any record I/O here... */
_Rformat(file1, "OPENFILE1 ");
printf("First name Last name State\n");
feedback = _Rreadn(file1, (void *) &amp;recBuf, sizeof(recBuf), __DFT);
while (feedback-&gt;num_bytes == sizeof(recBuf))
{
recCount++;
printf("%s ", strcnv400(recBuf.FNAME, sizeof(recBuf.FNAME)));
printf("%s ", strcnv400(recBuf.LNAME, sizeof(recBuf.LNAME)));
printf("%s\n", strcnv400(recBuf.STATE, sizeof(recBuf.STATE)));
feedback = _Rreadn(file1, (void *) &amp;recBuf,
sizeof(recBuf), __DFT);
}
printf("%d records selected\n", recCount);
/* Close the file */
_Rclose(file1);
/* close out the QDT file handle */
system("RCLRSC");
}</pre>
</div>
<div class="section"><h4 class="sectiontitle">Defining a join query</h4><p>This QQQQRY API example defines
a join query. The following is the equivalent SQL:</p>
<pre>SELECT * FROM OPENFILE1 A, OPENFILE2 B
WHERE STATE = 'AK' AND
A.ACCTNUM = B.CUSTNUM</pre>
<pre>/********************************************************************/
/* PROGRAM: QQAPI7 */
/* */
/* LANGUAGE: ILE C */
/* */
/* DESCRIPTION: THIS PROGRAM DEFINES A JOIN QUERY. */
/* */
/* APIs USED: QQQQRY */
/* */
/********************************************************************/
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;recio.h&gt;
#include &lt;qdbrtvfd.h&gt;
#include &lt;qqqqry.h&gt;
#include "qqapi.h"
/* get the record format from the file */
#pragma mapinc("recfmt","APIQQ/FORMAT1(FORMAT1)","input","p z",,)
#include "recfmt"
/* main - start of the program
*
* Flow:
* - initialize variables
* - override to set up sharing
* - build various QDT sections
* - build QDT with those sections
* - QQQQRY to run the query
* - open the data path
* - read the data and display it
* - close the data paths
*
*/
main()
{
/* record I/O variables */
_RIOFB_T *feedback;
_RFILE *file1;
APIQQ_FORMAT1_FORMAT1_i_t recBuf;
int recCount = 0;
/* Query variables */
QDBUFCB_T ufcbBuf;
char qdtBuf[QDT_SIZE];
char formatBuf[FORMAT_SIZE];
char selectBuf[SELECT_SIZE];
QDBQH_T *qdtPtr;
Qdb_Qddfmt_t *formatPtr;
QDBQS_T *selectPtr;
QDBQFHDR_T fileHdr;
QDBQN_T fileSpec[MAX_FILES];
QDBQJHDR_T joinHdr;
QDBQJFLD_T joinSpec[MAX_JOINTESTS];
int formatSize;
int fileSpecSize;
int selectSize;
int joinSize;
error_code errcod;
errcod.bytes_provided = 512;
/* initialize the pointers */
qdtPtr = (QDBQH_T *) qdtBuf;
formatPtr = (Qdb_Qddfmt_t *) formatBuf;
selectPtr = (QDBQS_T *) selectBuf;
/* initialize the headers */
initQDT(qdtPtr, QDBQTEMO, ON, ON, QDBQFINA, 0);
initFile(&amp;fileHdr, QDBQINNJ, QDBQMFOA);
initSelection(selectPtr);
initJoin(&amp;joinHdr);
/* set up override to allow sharing */
system("OVRDBF FILE(OPENFILE1) SHARE(*YES) LVLCHK(*NO)");
/* Note: If level checking is not done
(ie. no format on initUFCB) then
the override above must specify LVLCHK(*NO) */
/* build the individual QDT sections */
addFile(&amp;fileHdr, fileSpec, "OPENFILE1", NULL, NULL, NULL);
fileSpecSize = addFile(&amp;fileHdr, fileSpec, "OPENFILE2",
NULL, NULL, NULL);
formatSize = getRecordFmt(formatPtr, FORMAT_SIZE, "FORMAT1",
NULL, NULL);
joinSize = addJoinTest(&amp;joinHdr, joinSpec, "ACCTNUM", 1,
"CUSTNUM" , 2, "EQ");
/* build selection test: STATE = 'AK' */
addSelectField(selectPtr, "STATE", 1);
addSelectLiteral(selectPtr, "'AK'", 4);
selectSize = addSelectOperator(selectPtr, QDBQEQ);
/* initialize the UFCB */
initUFCB(&amp;ufcbBuf, QO_INPUT, NULL);
/* Now build the real QDT... */
addQDTsection(qdtPtr, (char *) &amp;fileHdr,
sizeof(fileHdr), &amp;qdtPtr-&gt;qdbqfilo);
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
addQDTsection(qdtPtr, (char *) formatPtr,
formatSize, &amp;qdtPtr-&gt;qdbqfldo);
addQDTsection(qdtPtr, (char *) &amp;joinHdr,
sizeof(joinHdr),&amp;qdtPtr-&gt;qdbqjoio);
addQDTsection(qdtPtr, (char *) joinSpec, joinSize, NULL);
addQDTsection(qdtPtr, (char *) selectPtr,
selectSize, &amp;qdtPtr-&gt;qdbqselo);
/* Finally, run the query! */
QQQQRY("RUNQRY ", (char *) &amp;ufcbBuf, qdtBuf, NULL, NULL,
&amp;errcod);
if (errcod.msgid[0])
{
printf("API QQQQRY failed\n");
printf("msgid = %7s\n", strcnv400(errcod.msgid,
sizeof(errcod.msgid)));
}
/* Now access the data */
if ((file1 = _Ropen("OPENFILE1", "rr riofb=N")) == NULL)
{
printf("Error opening file\n");
exit(1);
}
/* Perform any record I/O here... */
_Rformat(file1, "FORMAT1");
printf("Last name Item name\n");
feedback = _Rreadn(file1, (void *) &amp;recBuf, sizeof(recBuf), __DFT);
while (feedback-&gt;num_bytes == sizeof(recBuf))
{
recCount++;
printf("%s ", strcnv400(recBuf.LNAME, sizeof(recBuf.LNAME)));
printf("%s\n", strcnv400(recBuf.ITEMNAME,
sizeof(recBuf.ITEMNAME)));
feedback = _Rreadn(file1, (void *) &amp;recBuf,
sizeof(recBuf), __DFT);
}
printf("%d records selected\n", recCount);
/* Close the file */
_Rclose(file1);
/* close out the QDT file handle */
system("RCLRSC");
}</pre>
</div>
<div class="section"><h4 class="sectiontitle">Defining a join query with selection, grouping, and ordering</h4><p>This
QQQQRY API example defines a join query with selection, grouping, and ordering.
The following is the equivalent SQL:</p>
<pre>SELECT LNAME, FNAME, ITEMCODE, ITEMNAME, STATUS
FROM OPENFILE1, OPENFILE2
WHERE STATE = 'AK' AND CUSTNUM = ACCTNUM
GROUP BY LNAME, FNAME, ITEMCODE, ITEMNAME, STATUS
ORDER BY ITEMNAME</pre>
<pre>/********************************************************************/
/* PROGRAM: QQAPI11 */
/* */
/* LANGUAGE: ILE C */
/* */
/* DESCRIPTION: THIS PROGRAM DEFINES A JOIN QUERY WITH SELECTION */
/* GROUPING AND ORDERING. */
/* */
/* APIs USED: QQQQRY */
/* */
/********************************************************************/
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;qdbrtvfd.h&gt;
#include &lt;qqqqry.h&gt;
#include "qqapi.h"&gt;
/* main - start of the program
*
* Flow:
* - initialize variables
* - override to set up sharing
* - build various QDT sections
* - build QDT with those sections
* - QQQQRY to run the query
* - open the data path
* - read the data and display it
* - close the data paths
*
*/
main()
{
/* file I/O variables */
#define REC_SIZE 52
FILE *file1;
char recBuf[REC_SIZE];
int recCount = 0, found;
/* Query variables */
QDBUFCB_T ufcbBuf;
char qdtBuf[QDT_SIZE];
char formatBuf[FORMAT_SIZE];
char tempFormatBuf[FORMAT_SIZE];
char selectBuf[SELECT_SIZE];
QDBQH_T *qdtPtr;
Qdb_Qddfmt_t *formatPtr;
Qdb_Qddfmt_t *tempFormatPtr;
QDBQS_T *selectPtr;
QDBQFHDR_T fileHdr;
QDBQN_T fileSpec[MAX_FILES];
QDBQJHDR_T joinHdr;
QDBQJFLD_T joinSpec[MAX_JOINTESTS];
QDBQKH_T orderByHdr;
QDBQGH_T groupByHdr;
QDBQKF_T orderByFld[MAX_ORDERBY];
QDBQGF_T groupByFld[MAX_GROUPBY];
int formatSize;
int fileSpecSize;
int orderBySize;
int groupBySize;
int selectSize;
int joinSize;
error_code errcod;
memset( (void *) &amp;errcod, (char) 0, sizeof(error_code) );
errcod.bytes_provided = 512;
/* initialize the pointers */
qdtPtr = (QDBQH_T *) qdtBuf;
formatPtr = (Qdb_Qddfmt_t *) formatBuf;
tempFormatPtr = (Qdb_Qddfmt_t *) tempFormatBuf;
selectPtr = (QDBQS_T *) selectBuf;
/* initialize the headers */
initQDT(qdtPtr, QDBQTEMO, ON, ON, QDBQFINA, 0);
initFile(&amp;fileHdr, QDBQINNJ, QDBQMFOA);
initFormat(formatPtr, "JOINFMT01");
initOrderBy(&amp;orderByHdr);
initGroupBy(&amp;groupByHdr);
initSelection(selectPtr);
initJoin(&amp;joinHdr);
/* set up override to allow sharing */
system("OVRDBF FILE(OPENFILE1) SHARE(*YES) LVLCHK(*NO)");
/* Note: If level checking is not done
(ie. no format on initUFCB) then
the override above must specify LVLCHK(*NO) */
/* build the individual QDT sections */
addFile(&amp;fileHdr, fileSpec, "OPENFILE1", NULL, NULL, NULL);
fileSpecSize = addFile(&amp;fileHdr, fileSpec, "OPENFILE2",
NULL, NULL, NULL);
/* get the first format and copy some fields */
getRecordFmt(tempFormatPtr, FORMAT_SIZE, "OPENFILE1",
NULL, NULL);
copyField(formatPtr, "LNAME", 1, tempFormatPtr);
copyField(formatPtr, "FNAME", 1, tempFormatPtr);
/* clear the old format data */
memset(tempFormatPtr, 0, FORMAT_SIZE);
/* get the second format and copy some more fields */
getRecordFmt(tempFormatPtr, FORMAT_SIZE, "OPENFILE2", NULL, NULL);
copyField(formatPtr, "ITEMCODE", 2, tempFormatPtr);
copyField(formatPtr, "ITEMNAME", 2, tempFormatPtr);
formatSize = copyField(formatPtr, "STATUS", 2, tempFormatPtr);
/* set all the fields to input only */
setFieldUsage(formatPtr, NULL, 1);
/* build selection test: STATE = 'AK' */
addSelectField(selectPtr, "STATE", 1);
addSelectLiteral(selectPtr, "'AK'", 4);
selectSize = addSelectOperator(selectPtr, QDBQEQ);
joinSize = addJoinTest(&amp;joinHdr, joinSpec, "ACCTNUM", 1,
"CUSTNUM" , 2, "EQ");
orderBySize = addOrderBy(&amp;orderByHdr, orderByFld,
"ITEMNAME", OFF);
addGroupBy(&amp;groupByHdr, groupByFld, "LNAME", 0);
addGroupBy(&amp;groupByHdr, groupByFld, "FNAME", 0);
addGroupBy(&amp;groupByHdr, groupByFld, "ITEMCODE", 0);
addGroupBy(&amp;groupByHdr, groupByFld, "ITEMNAME", 0);
groupBySize = addGroupBy(&amp;groupByHdr, groupByFld, "STATUS", 0);
/* initialize the UFCB */
initUFCB(&amp;ufcbBuf, QO_INPUT, NULL);
/* set up for sequential only processing since it is a group by */
ufcbBuf.qufcb.parameter.seqonly = SEQUPROC;
ufcbBuf.qufcb.parameter.seqonoff = ON;
ufcbBuf.qufcb.parameter.numonoff = ON;
ufcbBuf.qufcb.parameter.numrecs = 1;
/* Now build the real QDT... */
addQDTsection(qdtPtr, (char *) &amp;fileHdr,
sizeof(fileHdr), &amp;qdtPtr-&gt;qdbqfilo);
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
addQDTsection(qdtPtr, (char *) formatPtr,
formatSize, &amp;qdtPtr-&gt;qdbqfldo);
addQDTsection(qdtPtr, (char *) &amp;joinHdr,
sizeof(joinHdr),&amp;qdtPtr-&gt;qdbqjoio);
addQDTsection(qdtPtr, (char *) joinSpec, joinSize, NULL);
addQDTsection(qdtPtr, (char *) selectPtr,
selectSize, &amp;qdtPtr-&gt;qdbqselo);
addQDTsection(qdtPtr, (char *) &amp;orderByHdr, sizeof(orderByHdr),
&amp;qdtPtr-&gt;qdbqkeyo);
addQDTsection(qdtPtr, (char *) orderByFld, orderBySize, NULL);
addQDTsection(qdtPtr, (char *) &amp;groupByHdr, sizeof(groupByHdr),
&amp;qdtPtr-&gt;qdbqgrpo);
addQDTsection(qdtPtr, (char *) groupByFld, groupBySize, NULL);
/* Finally, run the query! */
QQQQRY("RUNQRY ", (char *) &amp;ufcbBuf, qdtBuf,
NULL, NULL, &amp;errcod);
if (errcod.msgid[0])
{
printf("API QQQQRY failed\n");
printf("msgid = %7s\n", strcnv400(errcod.msgid,
sizeof(errcod.msgid)));
}
/* Now access the data */
if ((file1 = fopen("OPENFILE1", "rb")) == NULL)
{
printf("Error opening file\n");
exit(1);
}
/* Perform any record I/O here... */
printf("Last name First name Code \
Item St\n");
found = fread((void *) &amp;recBuf, REC_SIZE, 1, file1);
while (found)
{
recCount++;
printf("%s ", strcnv400(recBuf, 15));
printf("%s ", strcnv400(&amp;recBuf[15], 10));
printf("%s ", strcnv400(&amp;recBuf[25], 5));
printf("%s ", strcnv400(&amp;recBuf[30], 20));
printf("%s\n", strcnv400(&amp;recBuf[50], 2));
found = fread((void *) &amp;recBuf, REC_SIZE, 1, file1);
}
printf("%d records selected\n", recCount);
/* Close the file */
fclose(file1);
/* close out the QDT file handle */
system("RCLRSC");
}</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="apiexmp.htm" title="Contains example programs that use APIs and exit programs.">Examples: APIs</a></div>
</div>
</div>
</body>
</html>