MUSASHI C source: xtnjoin.c
0001: /*============================================================================*/
0002: /* 変更履歴 */
0003: /*----------------------------------------------------------------------------*/
0004: /* 1.0 : 新しいAPIに対応 2003/06/20 */
0005: /* 1.1 : 数値でソートしたキーを持つデータの動作不具合対処(API) 2003/08/07 */
0006: /*============================================================================*/
0007:
0008: #include <musashi.h>
0009: #include <stdlib.h>
0010:
0011: #include "xtnjoinHelp.h"
0012: struct mssComHelp comHelp={
0013: "xtnjoin", /* コマンド名 */
0014: "1.1", /* バージョン */
0015: HELPT, /* コマンドタイトル */
0016: HELPS, /* 要約 */
0017: HELPE, /* 利用例 */
0018: HELPR, /* 参照コマンド */
0019: HELPA, /* 作者情報 */
0020: HELPB, /* バグレポート情報 */
0021: HELPH /* ホームページ */
0022: };
0023:
0024: extern struct mssGlobalVariables mssGV;
0025:
0026: /*--グローバル変数*/
0027: static int fcT; /*入力データの項目数*/
0028: static int fcM; /*参照データの項目数*/
0029: static int statT; /*mssReadFRK(Tra)のステータス*/
0030: static int statM; /*mssReadFRK(Mst)のステータス*/
0031: static struct mssFPW *op;
0032: static MssOptKEY *OPTTKY;
0033: static MssOptKEY *OPTMKY;
0034: static MssOptFLD *OPTFLD;
0035:
0036: /**
0037: * # FUNCTION #
0038: * 現在読み込まれているTraとMstのキーの値を比較する
0039: */
0040: int keyCmp(
0041: struct mssFldRecKey *frkT,
0042: struct mssFldRecKey *frkM){
0043: int cmp;
0044: int i;
0045: int fnT;
0046: int fnM;
0047:
0048: if(statT==EOF) return(1); /*T>M*/
0049: if(statM==EOF) return(-1); /*T<M*/
0050:
0051: for(i=0; i<OPTTKY->flds->cnt; i++){
0052: fnT=MssFlds2num(OPTTKY->flds,i);
0053: fnM=MssFlds2num(OPTMKY->flds,i);
0054: cmp = strcmp( *(frkT->pnt+fnT), *(frkM->pnt+fnM) );
0055: if(cmp>0) return(1); /*T>M*/
0056: if(cmp<0) return(-1);/*T<M*/
0057: }
0058: return(0);
0059: }
0060:
0061: /**
0062: * # FUNCTION #
0063: * マスター項目としてstr配列のcnt個の要素を書き出す。
0064: * 行末の改行を出力する。
0065: */
0066: void writeMstFld(int cnt, char **str){
0067: int i;
0068: for(i=0; i<cnt-1; i++){
0069: mssWriteStr(*(str+MssFlds2num(OPTFLD->flds,i)),op);
0070: mssWriteDlm(op);
0071: }
0072: mssWriteStr(*(str+MssFlds2num(OPTFLD->flds,i)),op);
0073: mssWriteRet(op);
0074: }
0075:
0076: /**
0077: * # FUNCTION #
0078: * マスター項目として、cnt個のNULL値として書き出す。
0079: * 行末の改行を出力する。
0080: */
0081: void writeMstNul(int cnt){
0082: int i;
0083: for(i=0; i<cnt-1; i++){
0084: mssWriteNull(op); mssWriteDlm(op);
0085: }
0086: mssWriteNull(op); mssWriteRet(op);
0087: }
0088:
0089: /**
0090: * # FUNCTION #
0091: * トランザクション項目としてstr配列のcnt個の要素を書き出す。
0092: * 行末はスペースを出力する。
0093: */
0094: void writeTraFld(int cnt, char **str){
0095: int i;
0096: for(i=0; i<cnt; i++){
0097: mssWriteStr(*(str+i),op);
0098: mssWriteDlm(op);
0099: }
0100: }
0101:
0102: /**
0103: * # FUNCTION #
0104: * トランザクションキー項目の値が、にマスターキー項目に存在しないとき、
0105: * トランザクションのキー項目は、マスターの項目(str)を参照しながら出力し、
0106: * その他のトランザクション項目はNULL値を出力する。
0107: */
0108: void writeTraByMst(char **str){
0109: int kv;
0110: int i;
0111: for(i=0; i<fcT; i++){
0112: kv=*(OPTTKY->fldNo2optNo+i);
0113: if(kv!=-1){
0114: mssWriteStr(*(str+MssFlds2num(OPTMKY->flds,kv)),op);
0115: mssWriteDlm(op);
0116: }else{
0117: mssWriteNull(op); mssWriteDlm(op);
0118: }
0119: }
0120: }
0121:
0122: /**
0123: * # FUNCTION #
0124: * 現在のトランザクションとマスターを自然結合し、その結果を出力する。
0125: * frkTもしくはfrkMのいずれかにNULLを与えることにより、outerJOINを行い、
0126: * その結果を出力する。
0127: */
0128: void writeTM(struct mssFldRecKey *frkT,struct mssFldRecKey *frkM){
0129:
0130: /*マスターがEOFの時*/
0131: if(frkM==NULL){
0132: mssSeekTopFRK(frkT);
0133: while( EOF != mssReadFldRecFRK(frkT) ){
0134: writeTraFld(frkT->fldCnt,frkT->pnt);
0135: writeMstNul(OPTFLD->flds->cnt);
0136: mssGV.outCnt++;
0137: }
0138:
0139: /*トラがEOFの時*/
0140: }else if(frkT==NULL){
0141: mssSeekTopFRK(frkM);
0142: while( EOF != mssReadFldRecFRK(frkM) ){
0143: writeTraByMst(frkM->pnt);
0144: writeMstFld(OPTFLD->flds->cnt,frkM->pnt);
0145: mssGV.outCnt++;
0146: }
0147:
0148: /*トラ、マスターの両方ある場合*/
0149: }else{
0150: mssSeekTopFRK(frkT);
0151: while( EOF != mssReadFldRecFRK(frkT) ){
0152: mssSeekTopFRK(frkM);
0153: while( EOF != mssReadFldRecFRK(frkM) ){
0154: writeTraFld(frkT->fldCnt,frkT->pnt);
0155: writeMstFld(OPTFLD->flds->cnt,frkM->pnt);
0156: mssGV.outCnt++;
0157: }
0158: }
0159: }
0160: }
0161:
0162: /**
0163: * # FUNCTION #
0164: * writeNulMstのhash版。
0165: */
0166: void writeNulMstHash(struct mssHashFld *hash){
0167: struct mssHashNodeFld *node;
0168: int i,j;
0169:
0170: for(i=0; i<hash->hashVal; i++){ /*全hash値を見る*/
0171: node=*(hash->node+i);
0172: while(node != NULL){ /*hash値がiのノードを全て見る*/
0173: if(!node->endFlg){ /*そのノードが1回も検索されていなければ*/
0174: for(j=0; j<node->recCnt; j++){
0175: writeTraByMst(*(node->rec+j));
0176: writeMstFld(OPTFLD->flds->cnt,*(node->rec+j));
0177: mssGV.outCnt++;
0178: }
0179: }
0180: node=node->next;
0181: }
0182: }
0183: }
0184:
0185: /**
0186: * # FUNCTION #
0187: * writeTMのhash版。
0188: */
0189: void writeTMhash(struct mssFldRecKey *frkT,struct mssHashNodeFld *node){
0190: int i;
0191:
0192: /*マスターがNULLの時*/
0193: if(node==NULL){
0194: mssSeekTopFRK(frkT);
0195: while( EOF != mssReadFldRecFRK(frkT) ){
0196: writeTraFld(frkT->fldCnt,frkT->pnt);
0197: writeMstNul(OPTFLD->flds->cnt);
0198: mssGV.outCnt++;
0199: }
0200:
0201: /*トラ、マスターの両方ある場合*/
0202: }else{
0203: mssSeekTopFRK(frkT);
0204: while( EOF != mssReadFldRecFRK(frkT) ){
0205: for(i=0; i<node->recCnt; i++){
0206: writeTraFld(frkT->fldCnt,frkT->pnt);
0207: writeMstFld(OPTFLD->flds->cnt,*(node->rec+i));
0208: mssGV.outCnt++;
0209: }
0210: }
0211: }
0212: }
0213:
0214: int main(int argc, char *argv[]){
0215: /*============================================================================*/
0216: /* オプション宣言&定義 */
0217: /*============================================================================*/
0218: /*----------------------------------------------------------------------------*/
0219: /* 入力キー項目 */
0220: /*----------------------------------------------------------------------------*/
0221: MssOptKEY optTKY={
0222: OKEY, /* オプションタイプ */
0223: "k", /* キーワード(複数文字は不可) */
0224: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0225: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0226: "i", /* 対象とする入力データのキーワード(GUIで利用) */
0227: 0, /* デフォルト(このオプションが指定されなかったときの動作を指定) */
0228: /* 1:全ての行を異るキー値として扱う */
0229: /* 2:全ての行を同じキー値として扱う) */
0230: /* 0:その他(上記の意味解釈がない) */
0231: TKYT, /* このオプションのタイトル(Helpで表示) */
0232: TKYC /* このオプションのコメント(Helpで表示) */
0233: };
0234:
0235: /*----------------------------------------------------------------------------*/
0236: /* 参照キー項目 */
0237: /*----------------------------------------------------------------------------*/
0238: MssOptKEY optMKY={
0239: OKEY, /* オプションタイプ */
0240: "K", /* キーワード(複数文字は不可) */
0241: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0242: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0243: "m", /* 対象とする入力データのキーワード(GUIで利用) */
0244: 0, /* デフォルト(このオプションが指定されなかったときの動作を指定) */
0245: /* 1:全ての行を異るキー値として扱う */
0246: /* 2:全ての行を同じキー値として扱う) */
0247: /* 0:その他(上記の意味解釈がない) */
0248: MKYT, /* このオプションのタイトル(Helpで表示) */
0249: MKYC /* このオプションのコメント(Helpで表示) */
0250: };
0251:
0252: /*----------------------------------------------------------------------------*/
0253: /* 参照ファイル */
0254: /*----------------------------------------------------------------------------*/
0255: MssOptINF optMST={
0256: OINF, /* オプションタイプ */
0257: "m", /* キーワード(複数文字は不可) */
0258: 1, /* 0:オプション, 1:必須 */
0259: 1, /* 指定可能の最大ファイル数 */
0260: 0, /*1:file not foundのエラーで終了しない 0:する */
0261: MSTT, /* このオプションのタイトル(Helpで表示) */
0262: MSTC /* このオプションのコメント(Helpで表示) */
0263: };
0264:
0265: /*----------------------------------------------------------------------------*/
0266: /* 結合項目 */
0267: /*----------------------------------------------------------------------------*/
0268: MssOptFLD optFLD={
0269: OFLD, /* オプションタイプ */
0270: "f", /* キーワード(複数文字は不可) */
0271: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0272: MssFieldMaxCnt, /* 指定可能な最大項目数 */
0273: "m", /* 対象とする入力データのキーワード(GUIで利用) */
0274: 1, /* 正規表現を許可するかどうか(0:不可,1:可) */
0275: 1, /* 新項目名を指定できるかどうか(0:不可,1:可) */
0276: NULL, /* 項目オプション(%以下)で指定可能な文字 */
0277: /* ex) 指定不可の場合はNULL, "nr": "-f 項目名%rn"の指定可能 */
0278: FLDT, /* このオプションのタイトル(Helpで表示) */
0279: FLDC, /* このオプションのコメント(Helpで表示) */
0280: FLDF /* フラグについての説明(Helpで表示)複数の場合はカンマで区切る */
0281: };
0282:
0283: /*----------------------------------------------------------------------------*/
0284: /* マスターouterJoin */
0285: /*----------------------------------------------------------------------------*/
0286: MssOptFLG optMNL={
0287: OFLG, /* オプションタイプ */
0288: "N", /* キーワード(複数文字は不可) */
0289: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0290: MNLT, /* このオプションのタイトル(Helpで表示) */
0291: MNLC /* このオプションのコメント(Helpで表示) */
0292: };
0293:
0294: /*----------------------------------------------------------------------------*/
0295: /* 入力outerJoin */
0296: /*----------------------------------------------------------------------------*/
0297: MssOptFLG optTNL={
0298: OFLG, /* オプションタイプ */
0299: "n", /* キーワード(複数文字は不可) */
0300: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0301: TNLT, /* このオプションのタイトル(Helpで表示) */
0302: TNLC /* このオプションのコメント(Helpで表示) */
0303: };
0304:
0305: /*----------------------------------------------------------------------------*/
0306: /* 強制ハッシュJoin */
0307: /*----------------------------------------------------------------------------*/
0308: MssOptINT optHAS={
0309: OINT, /* オプションタイプ */
0310: "H", /* キーワード(複数文字は不可) */
0311: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0312: 1001, /* デフォルト(数値として指定) */
0313: 11, /* 最小値 */
0314: 100001, /* 最大値 */
0315: HAST, /* このオプションのタイトル(Helpで表示) */
0316: HASC /* このオプションのコメント(Helpで表示) */
0317: };
0318:
0319: /*----------------------------------------------------------------------------*/
0320: /* 入力ファイル */
0321: /*----------------------------------------------------------------------------*/
0322: MssOptINF optINF={
0323: OINF, /* オプションタイプ */
0324: "i", /* キーワード(複数文字は不可) */
0325: 0, /* 0:オプション, 1:必須 */
0326: 1, /* 指定可能の最大ファイル数 */
0327: 0, /*1:file not foundのエラーで終了しない 0:する */
0328: INFT, /* このオプションのタイトル(Helpで表示) */
0329: INFC /* このオプションのコメント(Helpで表示) */
0330: };
0331:
0332: /*----------------------------------------------------------------------------*/
0333: /* 出力ファイル */
0334: /*----------------------------------------------------------------------------*/
0335: MssOptOTF optOTF={
0336: OOTF, /* オプションタイプ */
0337: "o", /* キーワード(複数文字は不可) */
0338: 0, /* 0:オプション, 1:必須 */
0339: OTFT, /* このオプションのタイトル(Helpで表示) */
0340: OTFC /* このオプションのコメント(Helpで表示) */
0341: };
0342:
0343: /*----------------------------------------------------------------------------*/
0344: /* 圧縮出力 */
0345: /*----------------------------------------------------------------------------*/
0346: MssOptFLG optZIP={
0347: OFLG, /* オプションタイプ */
0348: "z", /* キーワード(複数文字は不可) */
0349: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0350: ZIPT, /* このオプションのタイトル(Helpで表示) */
0351: ZIPC /* このオプションのコメント(Helpで表示) */
0352: };
0353:
0354: /*----------------------------------------------------------------------------*/
0355: /* plain text */
0356: /*----------------------------------------------------------------------------*/
0357: MssOptFLG optTXT={
0358: OFLG, /* オプションタイプ */
0359: "t", /* キーワード(複数文字は不可) */
0360: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0361: TXTT, /* このオプションのタイトル(Helpで表示) */
0362: TXTC /* このオプションのコメント(Helpで表示) */
0363: };
0364:
0365: /*----------------------------------------------------------------------------*/
0366: /* ワークファイル用ディレクトリ名 */
0367: /*----------------------------------------------------------------------------*/
0368: MssOptSTR optTMP={
0369: OSTR, /* オプションタイプ */
0370: "T", /* キーワード(複数文字は不可) */
0371: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0372: MssTempDir, /* デフォルト */
0373: 1, /* 文字列の最小長 */
0374: MssFileNameMaxLen, /* 文字列の最大長 */
0375: TMPT, /* このオプションのタイトル(Helpで表示) */
0376: TMPC /* このオプションのコメント(Helpで表示) */
0377: };
0378:
0379: /*----------------------------------------------------------------------------*/
0380: /* オプションをまとめる */
0381: /*----------------------------------------------------------------------------*/
0382: void *opt[]={&optTKY,&optMKY,&optMST,&optFLD,&optMNL,&optTNL,&optHAS,
0383: &optINF,&optOTF,&optZIP,&optTXT,&optTMP,NULL};
0384:
0385: /*============================================================================*/
0386: /* 変数宣言&定義 */
0387: /*============================================================================*/
0388: struct mssHeader *hdT; /*入力ファイル用<head>タグ格納構造体*/
0389: struct mssHeader *hdM; /*参照ファイル用<head>タグ格納構造体*/
0390: struct mssHeader *hdo; /*出力ファイル用<head>タグ格納構造体*/
0391: struct mssFPR *fprT;/*入力ファイル構造体 */
0392: struct mssFPR *fprM;/*参照ファイル構造体 */
0393: struct mssFPW *fpw; /*出力ファイル構造体 */
0394: struct mssFields *sfT; /*ソート項目構造体 */
0395: struct mssFields *sfM; /*ソート項目構造体 */
0396: int sortedT; /*ソート済チェック用 */
0397: int sortedM; /*ソート済チェック用 */
0398:
0399: struct mssFldRecKey *frkT=NULL;
0400: struct mssFldRecKey *frkM=NULL;
0401: struct mssFldRecMax *frmM=NULL;
0402: struct mssFileInfo *fi; /*マスターのファイル情報*/
0403:
0404: struct mssHashFld *hash;
0405: struct mssHashNodeFld *hn;
0406:
0407: int mstIsSmall;
0408: int procType;
0409: int kc;
0410: int i;
0411:
0412: /*----------------------------------------------------------------------------*/
0413: /* 前処理 */
0414: /*----------------------------------------------------------------------------*/
0415: mssInit(argc,argv,&comHelp); /* シグナル処理などの初期化 */
0416: mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ */
0417: mssSetOption(opt,argc,argv); /* コマンドオプションの設定 */
0418:
0419: /*-Kが指定されていなければ-kをコピーする*/
0420: if(!optMKY.set){
0421: mssCpyOptKey(&optMKY,&optTKY);
0422: }
0423:
0424: fprT=mssOpenFPR(optINF.str,4); /*ファイルオープン*/
0425: fprM=mssOpenFPR(optMST.str,128); /*マスターファイルオープン*/
0426: hdT=mssReadHeader(fprT); /*項目名情報の読み込み*/
0427: hdM=mssReadHeader(fprM); /*項目名情報の読み込み*/
0428:
0429: mssSetOptKey(&optTKY, hdT); /* オプション項目をヘッダー項目に関連づけ*/
0430: mssSetOptKey(&optMKY, hdM); /* オプション項目をヘッダー項目に関連づけ*/
0431: mssSetOptFld(&optFLD, hdM); /* オプション項目をヘッダー項目に関連づけ*/
0432:
0433: /*traソート項目の作成*/
0434: sfT=mssInitFields();
0435: mssAddFieldsByFields(sfT,optTKY.flds);/* -k 項目をソート項目としてセット */
0436: mssSetFieldsSortPriority(sfT); /* ソート優先順位番号を登録順にふる */
0437: sortedT=mssChkSorted(sfT,hdT); /* ソート済かチェック */
0438:
0439: /*mstソート項目の作成*/
0440: sfM=mssInitFields();
0441: mssAddFieldsByFields(sfM,optMKY.flds);/* -k 項目をソート項目としてセット */
0442: mssSetFieldsSortPriority(sfM); /* ソート優先順位番号を登録順にふる */
0443: sortedM=mssChkSorted(sfM,hdM); /* ソート済かチェック */
0444:
0445: /*強制hashでなければ一万行を上限にマスターの情報を取得*/
0446: if(!optHAS.set){
0447: fi=mssGetFileInfo(optMST.str,10000);
0448:
0449: /*強制hashならば全行マスターの情報を取得*/
0450: }else{
0451: fi=mssGetFileInfo(optMST.str,0);
0452: }
0453:
0454: /*----------------------------------------------------------------------------*/
0455: /*前処理 */
0456: /*----------------------------------------------------------------------------*/
0457: /* Traは大きいという前提で考える*/
0458: /* TraSrt MstSrt MstSmall */
0459: /* 無 無 小 hash (1)*/
0460: /* 無 無 大 Tsrt+Msrt + keyBreak(2)*/
0461: /* 無 済 小 hash (1)*/
0462: /* 無 済 大 Tsrt + keyBreak(3)*/
0463: /* 済 無 小 Msrt + keyBreak(4)*/
0464: /* 済 無 大 Msrt + keyBreak(4)*/
0465: /* 済 済 小 keyBreak(5)*/
0466: /* 済 済 大 keyBreak(5)*/
0467:
0468: /*マスタが小さいかどうかのチェック*/
0469: if(!fi->readEnd){ /*最後まで読み切っていない*/
0470: mstIsSmall=0;
0471: }else{ /*その他は、smallであると判断*/
0472: mstIsSmall=1;
0473: }
0474: mssFree(fi);
0475:
0476: /*処理タイプの決定*/
0477: if(sortedT){
0478: if(sortedM){
0479: if(mstIsSmall) procType=5;
0480: else procType=5;
0481: }else{
0482: if(mstIsSmall) procType=4;
0483: else procType=4;
0484: }
0485: }else{
0486: if(sortedM){
0487: if(mstIsSmall) procType=1;
0488: else procType=3;
0489: }else{
0490: if(mstIsSmall) procType=1;
0491: else procType=2;
0492: }
0493: }
0494:
0495: /*強制hashの時は、強制的にtype1*/
0496: if(optHAS.set) procType=1;
0497:
0498: /*----------------------------------------------------------------------------*/
0499: /*出力ヘッダーの作成と出力 */
0500: /*----------------------------------------------------------------------------*/
0501: /*出力ヘッダーの初期化(タイトル等のコピー)*/
0502: hdo=mssInitCpyHeader(hdT);
0503:
0504: /*入力ヘッダの全項目を追加*/
0505: mssAddFieldsByFields(hdo->flds,hdT->flds);
0506:
0507: /*新項目名を追加する*/
0508: mssAddFieldsByStrList(hdo->flds,optFLD.newNam,optFLD.cnt);
0509:
0510: if(procType==2 || procType==3){
0511: mssSetFieldsSort(hdo->flds,sfT);
0512: }
0513:
0514: /*標準出力オープン+ヘッダーの出力*/
0515: fpw=mssOpenFPW(optOTF.str,optZIP.set,0);
0516: mssWriteHeader(hdo, fpw);
0517:
0518: /*----------------------------------------------------------------------------*/
0519: /*メインルーチン */
0520: /*----------------------------------------------------------------------------*/
0521: /*グローバル変数セット*/
0522: fcT=hdT->flds->cnt;
0523: fcM=hdM->flds->cnt;
0524: OPTTKY=&optTKY;
0525: OPTMKY=&optMKY;
0526: OPTFLD=&optFLD;
0527: op=fpw;
0528:
0529: /*hash join*/
0530: if(procType==1){
0531:
0532: /*ハッシュテーブルの作成*/
0533: frmM =mssInitFRM(fcM);
0534: mssReadFRM(fprM,frmM);
0535:
0536: /*全行読み込んでるはずなのでeofフラグがたっているはず*/
0537: if(!frmM->eof) {
0538: mssShowErrMsg("internal error in xtnjoin by hash");
0539: mssEnd(mssErrorNoDefault);
0540: }
0541:
0542: hash=mssInitHashFld(optHAS.val, optMKY.flds);
0543: for(i=0; i<frmM->recCnt; i++){
0544: mssHashInsertFld(hash, frmM->pnt+i*frmM->fldCnt);
0545: }
0546: /*mssShowHashFld(hash, frmM->fldCnt);*/
0547:
0548: frkT=mssInitFRK(fcT,&optTKY,optTMP.str);
0549: while(1){
0550: /*tra読み込み*/
0551: statT=mssReadFRK(fprT,frkT);
0552:
0553: /*Tra Endの時*/
0554: if(statT==EOF){
0555: if(optMNL.set) writeNulMstHash(hash);
0556: break;
0557: }
0558:
0559: mssGV.inCnt += frkT->keyRecCnt;
0560:
0561: /*Traのキー項目値がMstにあるかどうか*/
0562: mssReadFldRecFRK(frkT); /*tra一行だけ読み込み*/
0563: hn=mssHashMemberFld(hash, frkT->pnt, optTKY.flds);
0564: if(hn==NULL && !optTNL.set) continue;
0565:
0566: /*書き出し*/
0567: writeTMhash(frkT,hn);
0568: }
0569: mssFreeFRK(frkT);
0570: mssFreeFRM(frmM);
0571: mssFreeHashFld(hash);
0572:
0573: /*key break join*/
0574: }else{
0575: frkT=mssInitFRK(fcT,&optTKY,optTMP.str);
0576: frkM=mssInitFRK(fcM,&optMKY,optTMP.str);
0577: if(!sortedT){
0578: fprT=mssReopenFPRsort(fprT,4,sfT,hdT->flds->cnt,optTMP.str);
0579: }
0580: if(!sortedM){
0581: fprM=mssReopenFPRsort(fprM,4,sfM,hdM->flds->cnt,optTMP.str);
0582: }
0583:
0584: /*frk構造体から読み込むための変数。*/
0585: /*このプログラムでは確保はするけど開放しない。*/
0586: /*readRecFromFRKにてfr->pntは既にあるデータを指す。*/
0587: /*すなわちアドレスが変わる。だから。*/
0588: //frT=mssInitFRK(frkT->fldCnt);
0589: //frM=mssInitFRK(frkM->fldCnt);
0590:
0591: statT=mssReadFRK(fprT,frkT);
0592: statM=mssReadFRK(fprM,frkM);
0593: mssGV.inCnt += frkT->keyRecCnt;
0594:
0595: while(1){
0596:
0597: /*Tra,Mst両方Endの時*/
0598: if(statT==EOF && statM==EOF) break;
0599:
0600: /*TraだけEndの時*/
0601: if(statT==EOF){
0602: if(!optMNL.set) break;
0603: }
0604:
0605: /*MstだけEndの時*/
0606: if(statM==EOF){
0607: if(!optTNL.set) break;
0608: }
0609:
0610: /* Tra,Mstの最初の一行をキーの値の比較のために読み込む*/
0611: mssReadFldRecFRK(frkT);
0612: mssReadFldRecFRK(frkM);
0613: kc=keyCmp(frkT,frkM);
0614: if(kc == 1){ /*T>M*/
0615: if(optMNL.set) writeTM(NULL,frkM);
0616: statM=mssReadFRK(fprM,frkM);
0617: }else if(kc ==-1){ /*T<M*/
0618: if(optTNL.set) writeTM(frkT,NULL);
0619: statT=mssReadFRK(fprT,frkT);
0620: mssGV.inCnt += frkT->keyRecCnt;
0621: }else{ /*T==M*/
0622: writeTM(frkT,frkM);
0623: statT=mssReadFRK(fprT,frkT);
0624: mssGV.inCnt += frkT->keyRecCnt;
0625: statM=mssReadFRK(fprM,frkM);
0626: }
0627: }
0628: mssFreeFRK(frkT);
0629: mssFreeFRK(frkM);
0630: }
0631:
0632: /*----------------------------------------------------------------------------*/
0633: /*フッター出力&終了処理 */
0634: /*----------------------------------------------------------------------------*/
0635: mssWriteFooter(fpw); /*フッターの出力 */
0636: mssCloseFPR(fprT); /*入力ファイルのクローズ */
0637: mssCloseFPR(fprM); /*入力ファイルのクローズ */
0638: mssCloseFPW(fpw); /*出力ファイルのクローズ */
0639: mssFreeFields(sfT); /*ソート項目構造体の領域開放 */
0640: mssFreeFields(sfM); /*ソート項目構造体の領域開放 */
0641: mssFreeHeader(hdT); /*入力ヘッダ領域開放 */
0642: mssFreeHeader(hdM); /*入力ヘッダ領域開放 */
0643: mssFreeHeader(hdo); /*出力ヘッダ領域開放 */
0644: mssFreeOption(opt); /*オプション領域開放 */
0645: mssShowEndMsg(); /* 完了メッセージ */
0646: mssEnd(mssExitSuccess); /* 終了 */
0647: return(0); /* to avoid warning message */
0648: }