Unix Technical Forum

script for SQL Capture

This is a discussion on script for SQL Capture within the Informix forums, part of the Database Server Software category; --> Hello Some time ago, I was at a presentation where Mark Scranton had a script to capture the worst ...


Go Back   Unix Technical Forum > Database Server Software > Informix

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 04-20-2008, 08:08 AM
tomcaml@yahoo.com
 
Posts: n/a
Default script for SQL Capture

Hello

Some time ago, I was at a presentation where Mark Scranton had a
script to capture the worst running SQL on a machine. Since he is busy
touring, I thought I would ask the community if anyone had that
particular script.

Thanks in advance for looking.


tom

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 04-20-2008, 08:08 AM
Michael Mueller
 
Posts: n/a
Default Re: script for SQL Capture

Tom,

I don't know what script Mark Scranton had. But I have been using a
script a lot which you can find on my website:

http://michael-mueller-it.de/sqlstat.html

Michael

tomcaml@yahoo.com wrote:
> Hello
>
> Some time ago, I was at a presentation where Mark Scranton had a
> script to capture the worst running SQL on a machine. Since he is busy
> touring, I thought I would ask the community if anyone had that
> particular script.
>
> Thanks in advance for looking.
>
>
> tom
>

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 04-20-2008, 08:08 AM
tomcaml@yahoo.com
 
Posts: n/a
Default Re: script for SQL Capture

Thank you Michael. I will give it a whirl. Any gotchyas, environment
specifics, etc?

Tom

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 04-20-2008, 08:08 AM
tomcaml@yahoo.com
 
Posts: n/a
Default Re: script for SQL Capture

michael

i get an error reading header on this file after download


tom

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 04-20-2008, 08:08 AM
Michael Mueller
 
Posts: n/a
Default Re: script for SQL Capture

Can you be a bit more specific? What error and on what operating system?

Michael


tomcaml@yahoo.com wrote:
> michael
>
> i get an error reading header on this file after download
>
>
> tom
>

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 04-20-2008, 08:08 AM
Michael Mueller
 
Posts: n/a
Default Re: script for SQL Capture

Tom,

I'm attaching the major files. But I'm still interested to find out what
your downloading problem was.

Michael


tomcaml@yahoo.com wrote:
> michael
>
> i get an error reading header on this file after download
>
>
> tom
>



#!/usr/bin/ksh
if [ ! -x /usr/bin/ksh ]
then
echo "please change '#!/usr/bin/ksh' in line 1 to the path of a ksh"
echo "compatible shell and delete this if ..."
exit 1
fi

# Multiuser OnLine sql statistics using onstat commands (no sysmaster).
#
# Usage: SqlStat [ nsamples [ sleep-secs-per-sample [ nrepetitions ] ] ]
# or: SqlStat -h
#
# Results are in directory "erg.<hh:mm:ss>". There will be one such directory
# created for each repetition (parameter nrepetitions).
#
# Filename: erg.<hh:mm:ss>/0...0<num>.*_*
# <num> is the number of samples for the sql statement in this file.
# Just use "ls -l" to show files ordered by fequency of sql statements.
#
# If you have statements with varying constatns (no prepare, like
# "select ... where a = 123", "select ... where a = 987") use the
#
# use_scansql=y
#
# setting (and compile scansql.c), else you may want to use
# "use_scansql=n". The scansql program must be in the PATH if used
# (for example in the current directory if that's in the path).
#
# On some systems with huge shared memory (Solaris 8) starting and
# exiting onstat commands becomes very slow. Setting
#
# use_onstat_coprocess=y
#
# Makes the script communicate to a single onstat -i ksh coprocess.
# This option needs the cfilter.c program to be compiled and put in the PATH.

###### user settable options #############################################
#

# defaults for command line arguments nsamples, sleep-secs-per-sample
# and nrepetitions
nsamples=120
sleep=1
nrepetitions=1

# use scansql program = y/n
#use_scansql=y
use_scansql=n

# use onstat -i coprocess instead of many onstat commands, = y/n
#use_onstat_coprocess=y
use_onstat_coprocess=n

# output sql hostvariables (version >= 9.4), = y/n
#output_hv=y
output_hv=n

#
###### end of user settable options ######################################

if [ "$1" = -h ]
then
echo \
"Usage: SqlStat [ nsamples [ sleep-secs-per-sample [ nrepetitions ] ] ]"
echo \
" or: SqlStat -h"
echo \
" results will be put into directory erg.<hh:mm:ss>"
exit 0
fi

# assume most commands called here are in /usr/bin
export PATH=/usr/bin:$PATH

[ $# -ge 1 ] && nsamples="$1"
[ $# -ge 2 ] && sleep="$2"
[ $# -ge 3 ] && nrepetitions="$3"

if [ "$output_hv" = y ]
then
id | egrep 'uid=[0-9]*\(informix\)' >/dev/null 2>&1
if [ $? -ne 0 ]
then
echo "must run as user informix to use output_hv option"
exit 1
fi
fi

# remove temp files on exit
trap 'rm -f ../.SqlStat.tmp*' 0

# Finds program $1 in PATH and prints absolute path on stdout. Aborts
# if not found.
find_prog() {
h=`type "$1" 2>/dev/null`
e=$?
prog=`echo $h | awk '{print $NF}'`
[[ "$prog" != /* ]] && prog=`pwd`/$prog
if [ $e -ne 0 -o ! -x "$prog" ]
then
echo "cannot find program $1 in PATH"
exit 1
fi
echo $prog
}

# set $scansql either to cat or to absolute scansql program path
if [ "$use_scansql" = y ]
then
scansql=`find_prog scansql`
echo using $scansql
else
scansql=cat
fi

offmsg="shared memory not initialized for INFORMIXSERVER '$INFORMIXSERVER'"

# start onstat -i as a ksh coprocess and define onstat as a shell function
if [ "$use_onstat_coprocess" = y ]
then
cfilter=`find_prog cfilter`
echo using $cfilter

onstat -i |&
exec 6<&p 7>&p # save fds
onstatpid=$!
echo started coprocess onstat -i, pid $onstatpid

# temp file for cfilter program
ctmp=/tmp/.SqlStat.tmp99
rm -f $ctmp
if [ $? -ne 0 ]
then
echo cannot remove temp file $ctmp
exit 1
fi

trap '[ $onstatpid != 0 ] && kill -9 $onstatpid 2>/dev/null
rm -f ../.SqlStat.tmp* $ctmp' 0

# Function onstat() is supposed to behave like the original onstat
# command. It does it's job by communicating with the onstat -i
# coprocess using the external cfilter program. The shell always
# calls the function if defined.
onstat() {
if [ $onstatpid = 0 ] # coprocess already killed
then
echo "$offmsg"
return 1
fi

# export CFILTER_TRACE_FILE=/tmp/cfilter.trace
$cfilter "$*" $ctmp $onstatpid 4<&6 5>&7
# kill this job if oninit is down
# onstat -i is killed by trap 15
if [ $? -ne 0 ]
then
echo "$offmsg" 1>&2
kill $$ >/dev/null 2>&1
return 1 # not reached
fi

return 0
}
else # use_onstat_coprocess=n
onstat=`find_prog onstat`

onstat() {
$onstat $*
# kill this job if oninit is down
# but some older versions of onstat don't set the exit status!
if [ $? -ne 0 ]
then
echo "$offmsg" 1>&2
kill $$ >/dev/null 2>&1
return 1 # not reached
fi

return 0
}
fi

onstat_u () {
onstat -u | awk '$2 == "active," {exit}
f == 1 {print $1, $3}
$1 == "address" {f = 1}'
}

typeset -Z5 k=0

echo nsamples $nsamples, sleep-secs-per-sample $sleep, nrepetitions $nrepetitions

m=1
while [ $m -le $nrepetitions ]
do
echo "**** loop $m, `date`"

erg=erg.`date +%H:%M:%S`
mkdir $erg >/dev/null 2>&1
cd $erg
#rm -f *.*_*
> INFO

if [ "$use_onstat_coprocess" = y ]
then
echo "onstat -i coprocess $onstatpid" >> INFO
fi
echo "start: `date`, pid $$" >> INFO

num=0
n=1
while [ $n -le $nsamples ]
do
echo "$n of $nsamples "

# "rstcb | sid" Liste aller user
onstat_u | sort >../.SqlStat.tmp0

# find all interesting threads: rstcb, state, ...
onstat -g ath | egrep -v "netnorm|sm_read" | \
awk '/^ *[0-9].*sqlexec/ \
{printf("%s %s=%s=%s=%s=%s=%s\n", $3, $5, $6, $7, $8, $9, $10);}' \
>../.SqlStat.tmp1


i=`cat ../.SqlStat.tmp1 | wc -l`
if [ $i -gt 0 ]
then
# Choose a random thread
((i = (RANDOM % i ) + 1))
# get sid
sed -n -e "$i p" ../.SqlStat.tmp1 > ../.SqlStat.tmp2
sid=`join -o 2.2 ../.SqlStat.tmp2 ../.SqlStat.tmp0`

if [ "$sid" ]
then
# Get sql statement
onstat -g sql $sid > ../.SqlStat.tmp4
awk '/^Current SQL statement/ { f = 1; next; }
f == 1 { print; }
/^$/ { f = 0; } ' ../.SqlStat.tmp4 | \
$scansql >../.SqlStat.tmp3

if [ -s ../.SqlStat.tmp3 ]
then
((num += 1))
# file name: <counter>.<sum output 1>_<sum output 2>
set -- `sum ../.SqlStat.tmp3`
f=`ls *.$1_$2 2>/dev/null`
if [ "$f" ]
then
# file exists, increment counter part in filename
k=${f%%.*}
((k += 1))
f2=$k.$1_$2
mv $f $f2
else
echo >> ../.SqlStat.tmp3
let k=1
f2=$k.$1_$2
mv ../.SqlStat.tmp3 $f2
fi

# append time, sid, host, etc.
t=`date +%d.%m.%H:%M`
set -- `onstat -g ses $sid | \
awk 'f == 1 { print $2, $4, $5; exit; }
$1 == "id" { f = 1; }'`
if [ "$1" ]
then
fe=`ps -fp$2 | awk 'NR == 2 {print $8}'`
echo "@ $t, ses $sid, user $1, pid $2, host $3, fe $fe"\
>> $f2

echo " `awk '{print $2}' ../.SqlStat.tmp2`" | \
sed -e "s/=/ /g" >> $f2
if [ "$output_hv" = y ]
then # append host variables
awk '/^Host variables :/ { f = 1; next; }
f == 1 { print; }
/^$/ { if (f) exit; } ' ../.SqlStat.tmp4 \
>> $f2

fi
else
echo "@ $t: session exited" >> $f2
fi
fi
fi
fi

[ $sleep -gt 0 ] && sleep $sleep
((n += 1))
done

echo
echo "end: `date`" >> INFO
echo $num non empty samples >> INFO

((m += 1))

# for rm ../tmpfiles on exit avoid last cd ..
[ $m -le $nrepetitions ] && cd ..
done

/*
* Helper program for StatSql script to communicate with onstat -i ksh
* coprocess. Fd 5 is opened by the script for outputting commands into
* onstat -i and fd 4 for reading input from onstat -i.
* cfilter writes the command found in argv[1] to onstat -i followed by
* "- | tee /dev/null" which makes onstat -i flush it's output. Then it
* reads the onstat command's output until the next 'onstat> ' prompt is
* found. Any remaining input text is written to the argv[2] temp file for
* consumption by the next call. (Not needed for onstat 9.4, text ends with
* prompt. Needed for 7.24.UC8.) Signals SIGINT and redirected to the
* onstat -i process (with pid in argv[3]). They make onstat to interrupt
* it's running output and send the next prompt.
*
* All command output is written to fd 1 (stdout).
*
* Usage: cfilter "onstat-command-line" tmp-file-name
*
* To trace the program set env variable CFILTER_TRACE_FILE to a file pathname.
*
* Exit status: 0 = ok, 1 = shared memory not initialized, -1 = error.
*/

#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define L (8*1024)
char iBuf[L + 1];
char oBuf[L + 1];

/* to grep for a string in onstat output */
struct findStr {
char *str;
char *p;
};

FILE *tfp = NULL; /* trace file */
int tmpFd;

int onstatPid;

volatile int wErr = 0; /* changed in signal handler */

volatile struct findStr onstatPrompt; /* changed in signal handler */
volatile struct findStr onstatState;

int FoundStr(volatile struct findStr *fstr, int c);
ssize_t Read(int fd, char *buf, size_t l);
ssize_t Write(int fd, char *buf, size_t l);
void Error(char *str, ...);
void handler(int sig);

int
main(int argc, char **argv)
{
int ifd = 4, ofd = 5;
int l, n, k, lCnt, nl, e;
char *p;

/*
volatile int dbg = 1;
fprintf(stderr, "cfilter: debug me, pid %d\n", getpid());
while (dbg) {
sleep(1);
}
*/

if (argc != 4)
Error("usage: %s onstat-command tmp-file-name onstat-pid",
argv[0]);

if (strlen(argv[1]) > L - 50)
Error("onstat-command too long");

onstatPid = atoi(argv[3]);
/* redirect SIGINT, SIGPIPE, make write() return EPIPE error */
sigset(SIGINT, handler);
sigset(SIGPIPE, handler);

/* trace file */
p = getenv("CFILTER_TRACE_FILE");
if (p) {
tfp = fopen(p, "a");
if (!tfp)
Error("cannot open trace file %s", p);
setbuf(tfp, NULL);
}
if (tfp)
fprintf(tfp, "\n=== onstat %s, tmp %s, pid %d ===\n",
argv[1], argv[2], onstatPid);

/* open temp file */
do
tmpFd = open(argv[2], O_RDWR);
while (tmpFd < 0 && errno == EINTR);

if (tfp && tmpFd >= 0)
fprintf(tfp, "opened temp file\n");

/* output command to onstat -i */
sprintf(oBuf, "%s\n- | tee /dev/null\n", argv[1]);
l = strlen(oBuf);
if (Write(ofd, oBuf, l) != l) {
if (tfp)
fprintf(tfp, "write to onstat -i failed, errno %d\n",
errno);
return 1; /* shared memory not init ?? */
}

/* read the onstat command's output */
if (tfp)
fprintf(tfp, "reading ...\n");

/* first read and skip the header from the previous command's
* "- | tee /dev/null" output. It's terminated by a "\nonstat> " prompt.
*/
onstatPrompt.str = "\nonstat> ";
onstatPrompt.p = onstatPrompt.str;
nl = 1;
while ((l = Read(ifd, iBuf, L)) > 0) {
iBuf[l] = 0;
for (n = 0; n < l; ++n) {
if (tfp) {
if (nl) {
fprintf(tfp, "0: ");
nl = 0;
}
fputc(iBuf[n], tfp);
if (iBuf[n] == '\n')
nl = 1;
}
if (FoundStr(&onstatPrompt, iBuf[n])) {
if (tfp)
fprintf(tfp, "\n");
++n;
goto loop2;
}
}
}
if (l < 0)
Error("read in loop 1");
Error("first onstat prompt not found");

/* now read and the onstat -i command's output and write it to fd 1.
* Output is again terminated by a "\nonstat> " prompt. If oninit
* was shutdown (and maybe rebooted) while onstat -i was running
* the state in the header output is "-- Initialization --".
* Abort in this case.
*/
loop2:
onstatPrompt.p = onstatPrompt.str;
onstatState.str = "-- Initialization --";
onstatState.p = onstatState.str;
lCnt = 1;
k = 0;
nl = 1;
for (; {
if (n >= l) {
l = Read(ifd, iBuf, L);
if (l < 0)
Error("read in loop 2");
iBuf[l] = 0;
if (!l)
break;
n = 0;
}
for (; n < l; ++n) {
if (tfp) {
if (nl) {
fprintf(tfp, "%d: ", lCnt);
nl = 0;
}
fputc(iBuf[n], tfp);
if (iBuf[n] == '\n')
nl = 1;
}
if (lCnt <= 3) {
if (FoundStr(&onstatState, iBuf[n])) {
if (tfp)
fprintf(tfp,
"\nstate Initialization\n");
return 1;
}
}
if (FoundStr(&onstatPrompt, iBuf[n])) {
++n;
goto loopEnd;
}
if (k > L)
Error("line too long");
oBuf[k++] = iBuf[n];
if (iBuf[n] == '\n') {
/* ignore write errors, e.g. broken pipe,
* but skip further writes to fd 1
* after an error */
if (!wErr && (e = Write(1, oBuf, k)) != k) {
wErr = 1;
if(tfp)
fprintf(tfp,
"write error, ret %d errno %d\n",
e, errno);
}
k = 0;
++lCnt;
}
}
}
loopEnd:
if (*onstatPrompt.p)
Error("eof without \"%s\" prompt", onstatPrompt.str);
if (tfp)
fprintf(tfp, "\n");

/* put any remaining iBuf contents into temp file */
if (n < l) {
if (tfp)
fprintf(tfp, "putting %d bytes into temp file\n",
l - n);
tmpFd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (tmpFd < 0)
Error("cannot open temp file %s for writing",
argv[2]);
if ((e = Write(tmpFd, iBuf + n, l - n)) != l - n)
Error("write temp file, ret %d != %d", e, l - n);
close(tmpFd);
}

if (tfp)
fprintf(tfp, "finished\n");
return 0;
}

/* Find string descriped in fstr by comparing with the next byte in the
* input stream.
*/
int
FoundStr(volatile struct findStr *fstr, int c)
{
if (!*fstr->p)
return 0;

if (*fstr->p != c)
fstr->p = fstr->str;

if (*fstr->p == c) {
++fstr->p;
return !*fstr->p;
}
else {
fstr->p = fstr->str;
return 0;
}
}

ssize_t
Read(int fd, char *buf, size_t l)
{
int e;
int rfd = fd;

if (tmpFd >= 0)
rfd = tmpFd;

do
e = read(rfd, buf, l);
while (e < 0 && errno == EINTR);

if (e != 0 || tmpFd < 0)
return e;

/* e == 0 && tmpFd >= 0, eof on temp file */
if (tfp)
fprintf(tfp, "\neof on temp file\n");
if (ftruncate(tmpFd, 0) < 0)
Error("ftruncate");
close(tmpFd);
tmpFd = -1;

do
e = read(fd, buf, l);
while (e < 0 && errno == EINTR);

return e;
}

ssize_t
Write(int fd, char *buf, size_t l)
{
int e;

do
e = write(fd, buf, l);
while (e < 0 && errno == EINTR);

return e;
}

void
handler(int sig)
{
if (tfp)
fprintf(tfp, "\nkill(pid %d, sig %d)\n", onstatPid, sig);
if (kill(onstatPid, sig))
Error("cannot kill(pid %d, sig %d)", onstatPid, sig);

/* after the signal onstat outputs a prompt without leading \n */
if (*onstatPrompt.str == '\n') {
if (onstatPrompt.p == onstatPrompt.str)
++onstatPrompt.p;
++onstatPrompt.str;
}

wErr = 1;
}

void
Error(char *str, ...)
{
va_list ap;
int e = errno;

fprintf(stderr, "cfilter: ");
va_start(ap, str);
vfprintf(stderr, str, ap);
va_end(ap);
fprintf(stderr, "\n");
if (e)
fprintf(stderr, "errno %d: %s\n", e, strerror(e));
if (tfp)
fprintf(tfp, "\nerror %d, %s\n", e, str);

exit(-1);
}

all: scansql cfilter

scansql: scansql.c
cc -O scansql.c -o scansql

cfilter: cfilter.c
cc -O cfilter.c -o cfilter

/*
* Scan sql statement text and substitute fixed texts for constats of
* variouse types:
*
* numeric: <number>
* string: <string>
* datetime: <datetime>
* interval: <interval>
*
* All text is converted into lowercase. Whitespace is reduced to one blank
* and a \n is outputtet if the line would become too long. All sql comments
* (-- and { ... }) are removed.
*
* The purpose of all this is to output the same text for two statements with
* the same structure but different constants, whitespace etc.
*
* Usage: scansql [input-file [output-file] ]
*
* input-file and output-file can be '-' for stdin and stdout
*/

#include <stdio.h>
#include <strings.h>
#include <ctype.h>
#include <stdarg.h>

/* tokens */
#define T_NONE -1
#define T_EOF 0
#define T_BRACKET_OPEN 1
#define T_BRACKET_CLOSE 2
#define T_PLUS_MINUS 3
#define T_STRING 10
#define T_NUMBER 11
#define T_IDENTIFIER 100
#define T_TO 101
#define T_DATETIME 200
#define T_INTERVAL 201
#define T_DATETIME_IV_FQUAL 202
#define T_OTHER 999

int savedToken = T_NONE;

/* these consitute one token of tpe T_OTHER */
char *op2Tab[] = {
"||",
"::",
".*",
"<=",
">=",
"<>",
"!=",
"==",
NULL
};

struct IdTab {
char *name;
int token;
};

struct IdTab idTab[] = {
"datetime", T_DATETIME,
"interval", T_INTERVAL,
"to", T_TO,
"year", T_DATETIME_IV_FQUAL,
"month", T_DATETIME_IV_FQUAL,
"day", T_DATETIME_IV_FQUAL,
"hour", T_DATETIME_IV_FQUAL,
"minute", T_DATETIME_IV_FQUAL,
"second", T_DATETIME_IV_FQUAL,
"fraction", T_DATETIME_IV_FQUAL,
NULL, T_NONE
};

FILE *ifp, *ofp;

#define MAXLINE 80 /* min output line length, \n after next token */

#define SQLTXTMAX (64*1024)
char buf[SQLTXTMAX];

char tokenBuf[SQLTXTMAX];
char putbackBuf[SQLTXTMAX];

int NextToken(char *pText);
void PutBackToken(int token, char *pText);
int ScanNumber(char **pNext, char *pText);
void ParseDatetimeInterval();
void Error(char *str, ...);

int
main(int argc, char **argv)
{
int l, token;
char *p;
int plusMinus = 0;
int lineLen = 0;

if (argc < 2 || !strcmp(argv[1], "-"))
ifp = stdin;
else {
ifp = fopen(argv[1], "r");
if (!ifp)
Error("cannot open input file %s", argv[1]);
}

if (argc < 3 || !strcmp(argv[2], "-"))
ofp = stdout;
else {
ofp = fopen(argv[2], "w");
if (!ofp)
Error("cannot open input file %s", argv[2]);
}

l = fread(buf, 1, SQLTXTMAX - 1, ifp);
if (ferror(ifp))
Error("cannot read input file %s", argv[1]);
buf[l] = 0;

/* convert to lowercase */
for (p = buf; *p; ++p)
if (isupper(*p))
*p = tolower(*p);

/* parse and output statement */
while ((token = NextToken(tokenBuf)) != T_EOF) {
/* Informix SQL: "100 + - - - - 1" is 101 !!
* Print first '+' or '-', skip following ones.
*/
if (token == T_PLUS_MINUS) {
if (plusMinus)
continue;
plusMinus = 1;
}
else
plusMinus = 0;

switch (token) {
case T_STRING:
strcpy(tokenBuf, "<string>");
break;
case T_NUMBER:
strcpy(tokenBuf, "<number>");
break;
case T_DATETIME:
ParseDatetimeInterval();
strcpy(tokenBuf, "<datetime>");
break;
case T_INTERVAL:
ParseDatetimeInterval();
strcpy(tokenBuf, "<interval>");
break;
}

l = strlen(tokenBuf);
if (lineLen > 0 && lineLen + l + 1 >= MAXLINE) {
fprintf(ofp, "\n");
lineLen = 0;
}

if (lineLen) {
fprintf(ofp, " ");
lineLen += 1;
}

fprintf(ofp, "%s", tokenBuf);
lineLen += l;
}
if (lineLen)
fprintf(ofp, "\n");

return 0;
}

void
PutBackToken(int token, char *pText)
{
savedToken = token;
strcpy(putbackBuf, pText);
}

int
NextToken(char *pText)
{
static char *next = buf;
char *p, *p2;
int c, n, l;

if (savedToken != T_NONE) {
int t = savedToken;

savedToken = T_NONE;
strcpy(pText, putbackBuf);
return t;
}

/* Skip all leading sequences of whitspace, {} amd -- comments */
do {
while (isspace(*next))
++next;

p = next;

if (next[0] == '-' && next[1] == '-') {
next += 2;
while (*next && *next++ != '\n')
;
}

if (*next == '{') {
++next;
while (*next && *next++ != '}')
;
}
} while (p != next);

if (!*next)
return T_EOF;

p = next;
if (*p == '(') {
*pText++ = *p++;
*pText = 0;
next = p;
return T_BRACKET_OPEN;
}
else if (*p == ')') {
*pText++ = *p++;
*pText = 0;
next = p;
return T_BRACKET_CLOSE;
}
else if (*p == '\'' || *p == '\"') {
c = *p;
*pText++ = *p++;
while (*p) {
*pText++ = *p++;
if (p[-1] == c)
if (*p == c)
*pText++ = *p++;
else
break;
}
*pText = 0;
next = p;
return T_STRING;
}
else if (isalpha(*p) || *p == '_') {
p2 = pText;
*pText++ = *p++;
while (isalnum(*p) || *p == '_' || *p == '$')
*pText++ = *p++;
*pText = 0;
next = p;

for (n = 0; idTab[n].name; ++n)
if (!strcmp(idTab[n].name, p2))
return idTab[n].token;

return T_IDENTIFIER;
}
else if (*p == '+' || *p == '-') {
*pText++ = *p++;
*pText = 0;
next = p;
return T_PLUS_MINUS;
}
else if (isdigit(*p)) {
return ScanNumber(&next, pText);
}
else {
for (n = 0; op2Tab[n]; ++n) {
l = strlen(op2Tab[n]);
if (!strncmp(p, op2Tab[n], l))
break;
}
if (op2Tab[n]) {
strcpy(pText, op2Tab[n]);
next = p + l;
return T_OTHER;
}

*pText++ = *p++;
*pText = 0;
next = p;
return T_OTHER;
}

Error("NextToken end");
return T_EOF; /* not reached */
}

int
ScanNumber(char **pNext, char *pText)
{
char *p = *pNext;

while (isdigit(*p))
*pText++ = *p++;

if (*p == '.') {
*pText++ = *p++;
while (isdigit(*p))
*pText++ = *p++;
}

if (*p == 'e' || *p == 'E') {
*pText++ = *p++;
if (*p == '-')
*pText++ = *p++;
else if (*p == '+')
++p;
while (isdigit(*p))
*pText++ = *p++;
}

*pText = 0;
*pNext = p;

return T_NUMBER;
}

/* datetime and interval syntax:
*
* {T_DATETIME | T_INTERVAL} T_BRACKET_OPEN ... T_BRACKET_CLOSE \
* T_DATETIME_IV_FQUAL [prec] T_TO T_DATETIME_IV_FQUAL [prec]
*
* prec: T_BRACKET_OPEN T_NUMBER T_BRACKET_CLOSE
*/
void
ParseDatetimeInterval()
{
int token;

if (NextToken(tokenBuf) != T_BRACKET_OPEN)
return;

while ((token = NextToken(tokenBuf)) != T_BRACKET_CLOSE)
if (token == T_EOF)
return;

if (NextToken(tokenBuf) != T_DATETIME_IV_FQUAL)
return;

token = NextToken(tokenBuf);
if (token == T_BRACKET_OPEN) {
if (NextToken(tokenBuf) != T_NUMBER)
return;
if (NextToken(tokenBuf) != T_BRACKET_CLOSE)
return;
token = NextToken(tokenBuf);
}

if (token != T_TO)
return;

if (NextToken(tokenBuf) != T_DATETIME_IV_FQUAL)
return;

token = NextToken(tokenBuf);
if (token == T_BRACKET_OPEN) {
if (NextToken(tokenBuf) != T_NUMBER)
return;
if (NextToken(tokenBuf) != T_BRACKET_CLOSE)
return;
}
else
PutBackToken(token, tokenBuf);
}

void
Error(char *str, ...)
{
va_list ap;

va_start(ap, str);
vfprintf(stderr, str, ap);
va_end(ap);
fprintf( stderr, "\n" );

exit(1);
}

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 04-20-2008, 08:10 AM
tomcaml@yahoo.com
 
Posts: n/a
Default Re: script for SQL Capture

i get a directory checksum error.
i downloaded your file to my laptop (windows xp)
and then ftp that to my dev UNIX HP 11i server.


Tom

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 04-20-2008, 08:10 AM
Michael Mueller
 
Posts: n/a
Default Re: script for SQL Capture

Tom,

I assume you made some mistake in transferring the file (like using ftp
text mode?). I tried on HP myself without problems:

$ uname -a
HP-UX trift B.11.11 U 9000/800 832960671 unlimited-user license

$ ls -l
total 32
-rw-r--r-- 1 michaelm ts 15270 Apr 19 17:03 sqlstat.tar.gz

$ sum sqlstat.tar.gz
48564 30 sqlstat.tar.gz

$ gunzip sqlstat.tar.gz
$ tar tvf sqlstat.tar
rwxr-xr-x 1000/100 0 Mar 5 21:47 2005 sqlstat/
rw-r--r-- 1000/100 18007 Jul 21 22:43 2004 sqlstat/COPYING
rwxr-xr-x 1000/100 7571 Mar 5 21:47 2005 sqlstat/SqlStat
rwxr-xr-x 1000/100 0 Mar 4 22:17 2005 sqlstat/erg.21:25:37/
rw-r--r-- 1000/100 93 Mar 4 22:17 2005 sqlstat/erg.21:25:37/INFO
rw-r--r-- 1000/100 7726 Jul 21 22:41 2004
sqlstat/erg.21:25:37/00083.16476_1
rw-r--r-- 1000/100 1750 Jul 21 22:41 2004
sqlstat/erg.21:25:37/00018.16460_1
rw-r--r-- 1000/100 1231 Jul 21 22:41 2004
sqlstat/erg.21:25:37/00013.35489_1
rw-r--r-- 1000/100 7386 Mar 5 21:47 2005 sqlstat/cfilter.c
rw-r--r-- 1000/100 6961 Mar 4 22:13 2005 sqlstat/scansql.c
rw-r--r-- 1000/100 120 Mar 4 22:13 2005 sqlstat/makefile

Can you verify the file size (15270) and checksum (48564 30)?

Michael


tomcaml@yahoo.com wrote:
> i get a directory checksum error.
> i downloaded your file to my laptop (windows xp)
> and then ftp that to my dev UNIX HP 11i server.
>
>
> Tom
>

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9 (permalink)  
Old 04-20-2008, 08:10 AM
tomcaml@yahoo.com
 
Posts: n/a
Default Re: script for SQL Capture

Michael,

When i download it from your web site, the file says sqlstat.tar.tar,
not sqlstat.tar.gz as you have it.

$ sum sqlstat.tar.tar
48564 30 sqlstat.tar.tar

$ ls -l
-rw-r----- 1 informix informix 15270 Apr 19 09:27
sqlstat.tar.tar

$ uname -a
HP-UX B.11.11 U 9000/800 1488063140 unlimited-user license


Thanks,
Tom

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10 (permalink)  
Old 04-20-2008, 08:11 AM
Michael Mueller
 
Posts: n/a
Default Re: script for SQL Capture

tomcaml@yahoo.com wrote:
> Michael,
>
> When i download it from your web site, the file says sqlstat.tar.tar,
> not sqlstat.tar.gz as you have it.
>
> $ sum sqlstat.tar.tar
> 48564 30 sqlstat.tar.tar
>
> $ ls -l
> -rw-r----- 1 informix informix 15270 Apr 19 09:27
> sqlstat.tar.tar
>
> $ uname -a
> HP-UX B.11.11 U 9000/800 1488063140 unlimited-user license
>
>
> Thanks,
> Tom
>



Tom,

this looks fine so far, except for the name of the file (presumably
messed up by your download tool). I assume you then tried

tar xf sqlstat.tar.tar

and got an error. Try this:

file sqlstat.tar.tar # output: gzip compressed, not tar file!
mv sqlstat.tar.tar sqlstat.tar.gz
gunzip sqlstat.tar.gz
tar xf sqlstat.tar

Michael
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 12:20 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com