1520 lines
52 KiB
HTML
1520 lines
52 KiB
HTML
<?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 <stdio.h>
|
|
#include <string.h>
|
|
#include <qdbrtvfd.h>
|
|
#include <qqqqry.h>
|
|
#include <quscrtus.h>
|
|
#include <qusptrus.h>
|
|
#include <quscusat.h>
|
|
#include <qusrusat.h>
|
|
#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 < 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)) > len)
|
|
len = i;
|
|
if (len)
|
|
memcpy(dest, src, strlen(src));
|
|
if (i < 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 = &ufcbPtr-&gt;qufcb;
|
|
strcpy400((char *) ufcb->relver.release, REQ_REL,
|
|
sizeof(ufcb->relver.release));
|
|
strcpy400((char *) ufcb->relver.version, REQ_VER,
|
|
sizeof(ufcb->relver.version));
|
|
/* Blocked Records (BLKRCD) should be on if CPYFRMQRYF is used */
|
|
ufcb->markcnt.flg2brcd = ON;
|
|
ufcb->parameter.maximum = MAXFORMATS;
|
|
/* Set the open option */
|
|
if (openFlags&QO_INPUT)
|
|
ufcb->open.flagui = ON;
|
|
if (openFlags&QO_OUTPUT)
|
|
ufcb->open.flaguo = ON;
|
|
if (openFlags&QO_UPDATE)
|
|
ufcb->open.flaguu = ON;
|
|
if (openFlags&QO_DELETE)
|
|
ufcb->open.flagud = ON;
|
|
/* set up options to match _Ropen options */
|
|
ufcb->parameter.keyfdbk = KEYFDBK;
|
|
ufcb->parameter.keyonoff = ON; /* Key feedback ON */
|
|
ufcb->parameter.filedep = FILEDEP;
|
|
ufcb->parameter.fldonoff = ON; /* File dependent I/O ON */
|
|
/* turn the rest of the parameters off */
|
|
ufcb->parameter.seqonly = NOTSEQUPROC;
|
|
ufcb->parameter.primrln1 = NOTRECORDLTH;
|
|
ufcb->parameter.commitc = NOTCOMITCTL;
|
|
/* if the format is supplied,
|
|
define it in the UFCB and do level checking */
|
|
if (formatPtr != NULL)
|
|
{
|
|
ufcb->parameter.lvlchk = LEVELCK;
|
|
ufcb->parameter.lvlonoff = ON; /* Level check ON */
|
|
ufcb->parameter.curnum = 1; /* only one format */
|
|
/* set the format name and format level identifier */
|
|
ufcb->parameter.recfmts = FORMATSEQ;
|
|
memcpy(ufcb->parameter.formats[0].name, formatPtr->Qddfname,
|
|
sizeof(ufcb->parameter.formats[0].name));
|
|
memcpy(ufcb->parameter.formats[0].number, formatPtr->Qddfseq,
|
|
sizeof(ufcb->parameter.formats[0].number));
|
|
}
|
|
else /* no format and level checking */
|
|
{
|
|
ufcb->parameter.lvlchk = NOTLEVELCK;
|
|
ufcb->parameter.recfmts = NOTFORMATSEQ;
|
|
}
|
|
ufcb->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->qdbspcsize = sizeof(QDBQH_T);
|
|
/* QDT options... */
|
|
/* ordering not specified */
|
|
qdtHdr->qdbqkeyo = -1;
|
|
/* set optimize parameter (ALLIO, FIRSTIO, MINWAIT) */
|
|
if (optimize == QDBQFINA || optimize == QDBQFINF ||
|
|
optimize == QDBQFINM || optimize == QDBQFINC)
|
|
qdtHdr->qdbqfin = optimize; /* OPTIMIZE() parameter */
|
|
else
|
|
qdtHdr->qdbqfin = QDBQFINA; /* default to OPTIMIZE(*ALLIO) */
|
|
/* set allow copy data parameter (YES, NO, OPTIMIZE) */
|
|
if (alwCpyDta == QDBQTEMN || alwCpyDta == QDBQTEMO ||
|
|
alwCpyDta == QDBQTEMA)
|
|
qdtHdr->qdbqtem = alwCpyDta; /* ALWCPYDTA() parameter */
|
|
else
|
|
qdtHdr->qdbqtem = QDBQTEMA; /* default to ALWCPYDTA(*YES) */
|
|
/* status messages (YES, NO) */
|
|
qdtHdr->qdbqattr.qdbqnst = statusMsgs ? ON : OFF;
|
|
/* optimize all access path parameter (YES, NO) */
|
|
qdtHdr->qdbqdt_7.qdbqopta = optAllAp ? ON : OFF;
|
|
/* optimizer for n rows parameter */
|
|
qdtHdr->qdbq_optmrows = forRows > 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->qdbqmfop = joinType;
|
|
else
|
|
fileHdr->qdbqmfop = QDBQINNJ;
|
|
/* join order - any order or join as specified */
|
|
fileHdr->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->Qddfname, name, sizeof(formatHdr->Qddfname));
|
|
formatHdr->Qddfrcid = 65535;
|
|
formatHdr->Qddfsrcd = 65535;
|
|
formatHdr->Qddflgs.Qddfrsid = 1;
|
|
memset(formatHdr->Qddfseq, ' ', sizeof(formatHdr->Qddfseq));
|
|
memset(formatHdr->Qddftext, ' ', sizeof(formatHdr->Qddftext));
|
|
/* Format size (so far) */
|
|
formatHdr->Qddbyava = sizeof(Qdb_Qddfmt_t);
|
|
formatHdr->Qddbyrtn = formatHdr->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->qdbqsl = sizeof(QDBQS_T) - sizeof(selectHdr->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->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->qdbqfilnum == MAX_FILES)
|
|
return(0); /* no more files allowed */
|
|
/* increment the count of file specs */
|
|
i = fileHdr->qdbqfilnum++;
|
|
/* initialize the file spec area */
|
|
memset((void *) &fileSpec[i], (char) 0, sizeof(QDBQN_T));
|
|
fileSpecPtr = (QDBQFLMF_T *) &fileSpec[i].qdbqflmf;
|
|
/* fill in the data... */
|
|
strcpy400(fileSpecPtr->qdbqfile, filename,
|
|
sizeof(fileSpecPtr->qdbqfile));
|
|
if (library == NULL)
|
|
strcpy400(fileSpecPtr->qdbqlib, QDBQLIBL,
|
|
sizeof(fileSpecPtr->qdbqlib));
|
|
else
|
|
strcpy400(fileSpecPtr->qdbqlib, library,
|
|
sizeof(fileSpecPtr->qdbqlib));
|
|
if (member == NULL)
|
|
strcpy400(fileSpecPtr->qdbqmbr, QDBQFRST,
|
|
sizeof(fileSpecPtr->qdbqmbr));
|
|
else
|
|
strcpy400(fileSpecPtr->qdbqmbr, member,
|
|
sizeof(fileSpecPtr->qdbqmbr));
|
|
if (format == NULL)
|
|
strcpy400(fileSpecPtr->qdbqfmt, QDBQONLY,
|
|
sizeof(fileSpecPtr->qdbqfmt));
|
|
else
|
|
strcpy400(fileSpecPtr->qdbqfmt, format,
|
|
sizeof(fileSpecPtr->qdbqfmt));
|
|
/* return the amount of storage used in the file specs */
|
|
return(fileHdr->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(&fileLibname[10], QDBQLIBL, 10);
|
|
else
|
|
strcpy400(&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, &override,
|
|
"*LCL ", "*EXT ", &errcod);
|
|
if (errcod.msgid[0])
|
|
{
|
|
printf("API QDBRTVFD failed\n");
|
|
printf("msgid = %7s\n", strcnv400(errcod.msgid,
|
|
sizeof(errcod.msgid)));
|
|
}
|
|
if (formatPtr->Qddbyrtn != formatPtr->Qddbyava)
|
|
return(0); /* missing data */
|
|
/* return total storage used in format */
|
|
return(formatPtr->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->Qddbyava);
|
|
oldFieldPtr = (Qdb_Qddffld_t *) (oldFormatPtr + 1);
|
|
/* loop through all the fields, looking for a match */
|
|
for (i=0; i < oldFormatPtr->Qddffldnum; i++,
|
|
oldFieldPtr = (Qdb_Qddffld_t *) ((char *) oldFieldPtr +
|
|
oldFieldPtr->Qddfdefl))
|
|
/* if a match was found... */
|
|
if (memcmp(oldFieldPtr->Qddfflde, padField, 30) == 0)
|
|
{
|
|
/* copy the field over */
|
|
fieldSize = oldFieldPtr->Qddfdefl;
|
|
memcpy(fieldPtr, oldFieldPtr, fieldSize);
|
|
/* set the file number it was defined in */
|
|
fieldPtr->Qddfjref = fieldFile;
|
|
/* increment the format header information */
|
|
formatPtr->Qddffldnum++;
|
|
formatPtr->Qddfrlen += fieldPtr->Qddffldb;
|
|
formatPtr->Qddbyava += fieldSize;
|
|
formatPtr->Qddbyrtn = formatPtr->Qddbyava;
|
|
break;
|
|
}
|
|
/* return total storage used in format */
|
|
return(formatPtr->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 < formatPtr->Qddffldnum; i++,
|
|
fieldPtr = (Qdb_Qddffld_t *) ((char *) fieldPtr +
|
|
fieldPtr->Qddfdefl))
|
|
/* if all fields to be set or a match was found... */
|
|
if (fieldName == NULL ||
|
|
memcmp(fieldPtr->Qddfflde, padField, 30) == 0)
|
|
fieldPtr->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->qdbqsl);
|
|
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr->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->qdbqslen = itemSize + sizeof(QDBQSOPF_T);
|
|
/* length */
|
|
selectItemPtr->qdbqsitt = QDBQOPF; /* type is field */
|
|
/* now set up the field */
|
|
strcpy400(selectFldPtr->qdbqsofn, fieldName,
|
|
sizeof(selectFldPtr->qdbqsofn));
|
|
selectFldPtr->qdbqsofj = fieldFile;
|
|
/* update the header statistics */
|
|
selectHdr->qdbqsnum++; /* increment number of select specs */
|
|
selectHdr->qdbqsl += selectItemPtr->qdbqslen; /* total length */
|
|
/* return the total storage now in the selection section */
|
|
return(selectHdr->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 < 1)
|
|
return(0); /* invalid data */
|
|
/* set up all the sections for adding a literal */
|
|
selectItemPtr = (QDBQSIT_T *)
|
|
((char *) selectHdr + selectHdr->qdbqsl);
|
|
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr->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->qdbqslen = itemSize + sizeof(QDBQSOCH_T) + sizeLit;
|
|
selectItemPtr->qdbqsitt = QDBQOPC; /* literal type */
|
|
/* now set up the literal */
|
|
selectLitPtr->qdbqsocl = sizeLit; /* literal size */
|
|
selectLitPtr->qdbqsoft = '\xFF';
|
|
/* use job format for date/time fields */
|
|
memcpy(selectDataPtr, literal, sizeLit);
|
|
/* save the literal value */
|
|
/* update the header statistics */
|
|
selectHdr->qdbqsnum++; /* increment number of select specs */
|
|
selectHdr->qdbqsl += selectItemPtr->qdbqslen; /* total length */
|
|
/* return the total storage now in the selection section */
|
|
return(selectHdr->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->qdbqsl);
|
|
itemSize = sizeof(QDBQSIT_T) - sizeof(selectItemPtr->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->qdbqslen = itemSize + oprSize; /* length */
|
|
selectItemPtr->qdbqsitt = QDBQOPTR; /* operator type */
|
|
/* now set up the operator */
|
|
memcpy(selectOprPtr->qdbqsop, operator,
|
|
sizeof(selectOprPtr->qdbqsop));
|
|
/* wildcard operator set up */
|
|
if (memcmp(operator, QDBQWILD, 2) == 0)
|
|
{
|
|
selectOprPtr->qdbqswc1 = '_';
|
|
selectOprPtr->qdbqswc2 = '*';
|
|
selectWldPtr = (QDBQSOP2_T *) (selectOprPtr + 1);
|
|
memcpy(selectWldPtr->qdbqsdb1,"\42_", 2);
|
|
memcpy(selectWldPtr->qdbqsdb2,"\42*", 2);
|
|
}
|
|
/* update the header statistics */
|
|
selectHdr->qdbqsnum++; /* increment number of select specs */
|
|
selectHdr->qdbqsl += selectItemPtr->qdbqslen; /* total length */
|
|
/* return the total storage now in the selection section */
|
|
return(selectHdr->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->qdbqknum == MAX_ORDERBY)
|
|
return(0);
|
|
/* increment the order by spec counter */
|
|
i = orderByHdr->qdbqknum++;
|
|
/* add the new orderby data */
|
|
orderByFldPtr = &orderByFld[i];
|
|
memset((void *) orderByFldPtr, (char) 0, sizeof(QDBQKF_T));
|
|
strcpy400(orderByFldPtr->qdbqkfld, keyfield,
|
|
sizeof(orderByFldPtr->qdbqkfld));
|
|
orderByFldPtr->qdbqksq.qdbqksad = (descend) ? ON : OFF;
|
|
/* return the space used by the order by specs */
|
|
return(orderByHdr->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->qdbqgfnum == MAX_GROUPBY)
|
|
return(0);
|
|
/* increment the group by spec counter */
|
|
i = groupByHdr->qdbqgfnum++;
|
|
/* add the new groupby data */
|
|
groupByFldPtr = (QDBQGF_T *) &groupByFld[i];
|
|
memset((void *) groupByFldPtr, (char) 0, sizeof(QDBQGF_T));
|
|
strcpy400(groupByFldPtr->qdbqgfld, groupfield,
|
|
sizeof(groupByFldPtr->qdbqgfld));
|
|
groupByFldPtr->qdbqgflj = fromFile;
|
|
/* return the space used by the group by specs */
|
|
return(groupByHdr->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->qdbqjknum == MAX_JOINTESTS)
|
|
return(0);
|
|
/* increment the join test counter */
|
|
i = joinHdr->qdbqjknum++;
|
|
memset((void *) &joinSpec[i], (char) 0, sizeof(QDBQJFLD_T));
|
|
/* add the new join data */
|
|
joinSpecPtr = &joinSpec[i];
|
|
strcpy400(joinSpecPtr->qdbqjfnm, fromFld,
|
|
sizeof(joinSpecPtr->qdbqjfnm));
|
|
joinSpecPtr->qdbqjfnum = fromFile; /* 1, 2, 3, etc */
|
|
strcpy400(joinSpecPtr->qdbqjtnm, toFld,
|
|
sizeof(joinSpecPtr->qdbqjtnm));
|
|
joinSpecPtr->qdbqjtnum = toFile; /* 1, 2, 3, etc */
|
|
/* Join operator - see #defines in QQ API include */
|
|
strcpy400(joinSpecPtr->qdbqjop, joinOp,
|
|
sizeof(joinSpecPtr->qdbqjop));
|
|
/* set size of entire join spec */
|
|
joinHdr->qdbqjln += sizeof(QDBQJFLD_T);
|
|
/* return the space used by the join tests */
|
|
return(joinHdr->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->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->qdbspcsize;
|
|
/* update the QDT size */
|
|
qdtHdr->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,
|
|
&value,
|
|
"*ALL ",
|
|
text,
|
|
"*YES ",
|
|
&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,&name[10],10);
|
|
chgAttr.numAttrs = 1;
|
|
chgAttr.key = 3; /* Auto extend */
|
|
chgAttr.length = sizeof(char);
|
|
chgAttr.data.autoExtend = '1';
|
|
QUSCUSAT(library,
|
|
name,
|
|
&chgAttr,
|
|
&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,
|
|
&usrSpcPtr,
|
|
&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->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->storagePtr - 16);
|
|
/* Write the access plan size out at the start */
|
|
memcpy(usrSpcPtr, (void *) &accessPlan->size,
|
|
sizeof(accessPlan->size));
|
|
#ifdef QQDEBUG
|
|
printf("AP size = %ld\n", accessPlan->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->storagePtr +
|
|
accessPlan->size);
|
|
/* Write the QDT size out */
|
|
memcpy(usrSpcPtr, &qdtPtr->qdbspcsize, sizeof(qdtPtr->qdbspcsize));
|
|
#ifdef QQDEBUG
|
|
printf("qdt size = %ld\n", qdtPtr->qdbspcsize);
|
|
#endif
|
|
/* Move up the user space pointer */
|
|
usrSpcPtr = (_SPCPTR) ((char *) usrSpcPtr + 16);
|
|
/* Write the QDT itself out */
|
|
memcpy(usrSpcPtr, qdtPtr, qdtPtr->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->storagePtr +
|
|
accessPlan->size);
|
|
/* Write the QDT size out */
|
|
memcpy((void *) &qdtPtr->qdbspcsize, usrSpcPtr,
|
|
sizeof(qdtPtr->qdbspcsize));
|
|
#ifdef QQDEBUG
|
|
printf("qdt size = %ld\n", qdtPtr->qdbspcsize);
|
|
#endif
|
|
/* Move up the user space pointer */
|
|
usrSpcPtr = (_SPCPTR) ((char *) usrSpcPtr + 16);
|
|
/* Write the QDT itself out */
|
|
memcpy((void *) qdtPtr, usrSpcPtr, qdtPtr->qdbspcsize);
|
|
return(qdtPtr->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, &usrSpcPtr, &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(&usrSpcAttr,
|
|
sizeof(Qus_SPCA_0100_t),
|
|
"SPCA0100",
|
|
name,
|
|
&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 ==> %d\n",usrSpcAttr.Bytes_Returned);
|
|
printf("Bytes Available ==> %d\n",usrSpcAttr.Bytes_Available);
|
|
printf("Space Size ==> %d\n",usrSpcAttr.Space_Size);
|
|
printf("Auto Extend ==> %c\n",
|
|
usrSpcAttr.Automatic_Extendability);
|
|
}
|
|
#endif
|
|
/* Pull the access plan size out first */
|
|
memcpy((void *) &accessPlan->size, usrSpcPtr,
|
|
sizeof(accessPlan->size));
|
|
#ifdef QQDEBUG
|
|
printf("AP size = %ld\n", accessPlan->size);
|
|
#endif
|
|
/* Now move to the access plan itself (on 16 byte boundary) */
|
|
accessPlan->storagePtr = (_SPCPTR) ((char*) usrSpcPtr + 16);
|
|
|
|
return(accessPlan->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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <recio.h>
|
|
#include <qdbrtvfd.h>
|
|
#include <qqqqry.h>
|
|
#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(&fileHdr, QDBQINNJ, QDBQMFOA);
|
|
initOrderBy(&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(&fileHdr, fileSpec, "OPENFILE1",
|
|
NULL, NULL, NULL);
|
|
formatSize = getRecordFmt(formatPtr, FORMAT_SIZE, "OPENFILE1",
|
|
NULL, NULL);
|
|
orderBySize = addOrderBy(&orderByHdr, orderByFld, "LNAME", OFF);
|
|
|
|
/* initialize the UFCB */
|
|
initUFCB(&ufcbBuf, QO_INPUT, formatPtr);
|
|
|
|
/* Now build the real QDT... */
|
|
addQDTsection(qdtPtr, (char *) &fileHdr,
|
|
sizeof(fileHdr), &qdtPtr->qdbqfilo);
|
|
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
|
|
addQDTsection(qdtPtr, (char *) formatPtr,
|
|
formatSize, &qdtPtr->qdbqfldo);
|
|
addQDTsection(qdtPtr, (char *) &orderByHdr, sizeof(orderByHdr),
|
|
&qdtPtr->qdbqkeyo);
|
|
addQDTsection(qdtPtr, (char *) orderByFld, orderBySize, NULL);
|
|
|
|
/* Finally, run the query! */
|
|
QQQQRY("RUNQRY ", (char *) &ufcbBuf, qdtBuf, NULL, NULL,
|
|
&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 *) &recBuf, sizeof(recBuf), __DFT);
|
|
while (feedback->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 *) &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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <recio.h>
|
|
#include <qdbrtvfd.h>
|
|
#include <qqqqry.h>
|
|
#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(&fileHdr, QDBQINNJ, QDBQMFOA);
|
|
initSelection(selectPtr);
|
|
initJoin(&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(&fileHdr, fileSpec, "OPENFILE1", NULL, NULL, NULL);
|
|
fileSpecSize = addFile(&fileHdr, fileSpec, "OPENFILE2",
|
|
NULL, NULL, NULL);
|
|
formatSize = getRecordFmt(formatPtr, FORMAT_SIZE, "FORMAT1",
|
|
NULL, NULL);
|
|
joinSize = addJoinTest(&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(&ufcbBuf, QO_INPUT, NULL);
|
|
|
|
/* Now build the real QDT... */
|
|
addQDTsection(qdtPtr, (char *) &fileHdr,
|
|
sizeof(fileHdr), &qdtPtr->qdbqfilo);
|
|
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
|
|
addQDTsection(qdtPtr, (char *) formatPtr,
|
|
formatSize, &qdtPtr->qdbqfldo);
|
|
addQDTsection(qdtPtr, (char *) &joinHdr,
|
|
sizeof(joinHdr),&qdtPtr->qdbqjoio);
|
|
addQDTsection(qdtPtr, (char *) joinSpec, joinSize, NULL);
|
|
addQDTsection(qdtPtr, (char *) selectPtr,
|
|
selectSize, &qdtPtr->qdbqselo);
|
|
|
|
/* Finally, run the query! */
|
|
QQQQRY("RUNQRY ", (char *) &ufcbBuf, qdtBuf, NULL, NULL,
|
|
&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 *) &recBuf, sizeof(recBuf), __DFT);
|
|
while (feedback->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 *) &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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <qdbrtvfd.h>
|
|
#include <qqqqry.h>
|
|
#include "qqapi.h">
|
|
|
|
|
|
|
|
/* 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 *) &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(&fileHdr, QDBQINNJ, QDBQMFOA);
|
|
initFormat(formatPtr, "JOINFMT01");
|
|
initOrderBy(&orderByHdr);
|
|
initGroupBy(&groupByHdr);
|
|
initSelection(selectPtr);
|
|
initJoin(&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(&fileHdr, fileSpec, "OPENFILE1", NULL, NULL, NULL);
|
|
fileSpecSize = addFile(&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(&joinHdr, joinSpec, "ACCTNUM", 1,
|
|
"CUSTNUM" , 2, "EQ");
|
|
orderBySize = addOrderBy(&orderByHdr, orderByFld,
|
|
"ITEMNAME", OFF);
|
|
addGroupBy(&groupByHdr, groupByFld, "LNAME", 0);
|
|
addGroupBy(&groupByHdr, groupByFld, "FNAME", 0);
|
|
addGroupBy(&groupByHdr, groupByFld, "ITEMCODE", 0);
|
|
addGroupBy(&groupByHdr, groupByFld, "ITEMNAME", 0);
|
|
groupBySize = addGroupBy(&groupByHdr, groupByFld, "STATUS", 0);
|
|
|
|
|
|
/* initialize the UFCB */
|
|
initUFCB(&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 *) &fileHdr,
|
|
sizeof(fileHdr), &qdtPtr->qdbqfilo);
|
|
addQDTsection(qdtPtr, (char *) fileSpec, fileSpecSize, NULL);
|
|
addQDTsection(qdtPtr, (char *) formatPtr,
|
|
formatSize, &qdtPtr->qdbqfldo);
|
|
addQDTsection(qdtPtr, (char *) &joinHdr,
|
|
sizeof(joinHdr),&qdtPtr->qdbqjoio);
|
|
addQDTsection(qdtPtr, (char *) joinSpec, joinSize, NULL);
|
|
addQDTsection(qdtPtr, (char *) selectPtr,
|
|
selectSize, &qdtPtr->qdbqselo);
|
|
addQDTsection(qdtPtr, (char *) &orderByHdr, sizeof(orderByHdr),
|
|
&qdtPtr->qdbqkeyo);
|
|
addQDTsection(qdtPtr, (char *) orderByFld, orderBySize, NULL);
|
|
addQDTsection(qdtPtr, (char *) &groupByHdr, sizeof(groupByHdr),
|
|
&qdtPtr->qdbqgrpo);
|
|
addQDTsection(qdtPtr, (char *) groupByFld, groupBySize, NULL);
|
|
|
|
/* Finally, run the query! */
|
|
QQQQRY("RUNQRY ", (char *) &ufcbBuf, qdtBuf,
|
|
NULL, NULL, &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 *) &recBuf, REC_SIZE, 1, file1);
|
|
while (found)
|
|
{
|
|
recCount++;
|
|
printf("%s ", strcnv400(recBuf, 15));
|
|
printf("%s ", strcnv400(&recBuf[15], 10));
|
|
printf("%s ", strcnv400(&recBuf[25], 5));
|
|
printf("%s ", strcnv400(&recBuf[30], 20));
|
|
printf("%s\n", strcnv400(&recBuf[50], 2));
|
|
found = fread((void *) &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> |