8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-28 04:03:03 +01:00
firebird-mirror/src/misc/relations.epp
2003-07-14 16:55:04 +00:00

621 lines
16 KiB
Plaintext

/*
* PROGRAM: JRD Access Method
* MODULE: relations.epp
* DESCRIPTION: Relations include file generator
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Blas Rodriguez Somoza blas@puertareal.com
*/
#include "firebird.h"
#include "../jrd/ib_stdio.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "../jrd/common.h"
#include "../jrd/gds.h"
#include "../jrd/msg_encode.h"
// needed for unlink in MinGW 3.0 rc2
#ifdef MINGW
#include <io.h>
#endif
/* The MSG.GDB database is found under the /msgs component subdirectory.
Use links or logicals to point it there, thanks! AMG */
DATABASE DB = FILENAME "metadata.fdb";
#define RELATIONS_H "relations.h"
#define IDS_H "ids.h"
#define FIELDS_H "fields.h"
#define NAMES_H "names.h"
static void build_relations_h(void);
static void build_fields_h(void);
static void build_names_h(void);
static void move_if_not_identical(char *, char *, char*);
static void add_text(IB_FILE *, int, const char **);
static char* genDirectory = NULL;
#define CHECK_OPEN(f, name, tmp, mode) \
if (((f) = ib_fopen ((tmp), (mode))) == NULL) \
{ \
ib_fprintf (ib_stderr, "CODES: Unable to open %s in filemode %s for %s\n", \
(tmp), (mode), (name)); \
exit (FINI_ERROR); \
}
#define CHECK_CLOSE(f, name, tmp, mode, dir) \
ib_fclose (f);\
move_if_not_identical ((name), (tmp), (dir))
#define CSTYLE 1
#define PASSTYLE 2
#define FTNSTYLE 3
#define FAC_SQL_POSITIVE 14 /* facility for positive SQL codes */
#define FAC_SQL_NEGATIVE 13 /* ditto for negative codes */
static const char *license[] = {
"The contents of this file are subject to the Interbase Public",
"License Version 1.0 (the \"License\"); you may not use this file",
"except in compliance with the License. You may obtain a copy",
"of the License at http://www.Inprise.com/IPL.html",
"",
"Software distributed under the License is distributed on an",
"\"AS IS\" basis, WITHOUT WARRANTY OF ANY KIND, either express",
"or implied. See the License for the specific language governing",
"rights and limitations under the License.",
"",
"The content of this file was generated by the Firebird project",
"using the program jrd/relations.epp",
0
};
static const char *warn[] = {
"",
"*** WARNING *** - This file is automatically generated by relations.epp - do not edit!",
"",
0
};
int CLIB_ROUTINE main( int argc, char *argv[])
{
/*************************************
*
* m a i n
*
**************************************
*
* Functional description
* Generate both code definition
* include file and message text
* include file.
*
**************************************/
READY
ON_ERROR
ib_printf("Attach failed.\n");
gds__print_status(gds_status);
exit(FINI_ERROR);
END_ERROR;
// See if the user has specified an optional output directory
if (argc >=1)
genDirectory = argv[1];
START_TRANSACTION;
build_relations_h();
build_fields_h();
build_names_h();
COMMIT;
FINISH;
return 0;
}
static void build_relations_h(void){
/*******************************************
*
* b u i l d _ r e l a t i o n s _ h
*
*******************************************
*
* Functional desciption
* Function creates the msgfac.h
* file which contains a listing of valid
* facilities for the error codes.
*
*******************************************/
IB_FILE *relations;
IB_FILE *ids;
/* Open files in the current directory */
CHECK_OPEN(relations, RELATIONS_H, "tmpcode1", "w");
CHECK_OPEN(ids, IDS_H, "tmpcode2", "w");
add_text(relations, CSTYLE, license);
add_text(relations, CSTYLE, warn);
ib_fprintf(relations, "/*\n");
ib_fprintf(relations, " * MODULE: relations.h\n");
ib_fprintf(relations, " * DESCRIPTION: System relation definitions\n");
ib_fprintf(relations, " *\n");
ib_fprintf(relations, " */\n");
add_text(ids, CSTYLE, license);
add_text(ids, CSTYLE, warn);
ib_fprintf(ids, "/*\n");
ib_fprintf(ids, " * MODULE: ids.h\n");
ib_fprintf(ids, " * DESCRIPTION: System relation definitions\n");
ib_fprintf(ids, " *\n");
ib_fprintf(ids, " */\n");
bool first= true;
char prev_rel_name[31];
char rel_name[31];
char cor_rel_name[31];
char fld_name[31];
char cor_fld_name[31];
char src_fld_name[31];
char cor_src_fld_name[31];
int upd_flag;
int fld_id;
EXEC SQL
DECLARE relation_join CURSOR FOR
SELECT rel_fld_tab.RDB$RELATION_NAME, rel_fld_tab.RDB$FIELD_NAME
, rel_fld_tab.RDB$UPDATE_FLAG, rel_fld_tab.RDB$FIELD_ID
, rel_fld_tab.RDB$FIELD_SOURCE
FROM RDB$RELATIONS rel_tab, RDB$RELATION_FIELDS rel_fld_tab
WHERE rel_tab.RDB$RELATION_NAME = rel_fld_tab.RDB$RELATION_NAME
AND rel_tab.RDB$SYSTEM_FLAG='1'
ORDER BY rel_tab.RDB$RELATION_ID, rel_fld_tab.RDB$FIELD_ID
/* Open the cursor. */
EXEC SQL
OPEN relation_join;
/*
* Select and display all rows.
*/
while (SQLCODE == 0)
{
EXEC SQL
FETCH relation_join INTO :rel_name, :fld_name, :upd_flag, :fld_id
, :src_fld_name;
if (SQLCODE !=0)
break;
if (first || strcmp(prev_rel_name,rel_name)!=0){
if (!first)
ib_fprintf(relations, "END_RELATION\n");
sscanf(rel_name,"RDB$%s",cor_rel_name);
if (strcmp(cor_rel_name,"ROLES")==0)
ib_fprintf(relations, "RELATION(nam_%s, rel_%s, ODS_9_0)\n"
, cor_rel_name, cor_rel_name);
else
ib_fprintf(relations, "RELATION(nam_%s, rel_%s, ODS_8_0)\n"
, cor_rel_name, cor_rel_name);
sprintf(prev_rel_name,"%s",rel_name);
first = false;
}
/*
* If FETCH returns with -100, the processing will jump
* to AllDone before the following printf is executed.
*/
sscanf(fld_name,"RDB$%s",cor_fld_name);
sscanf(src_fld_name,"RDB$%s",cor_src_fld_name);
ib_fprintf(relations, "\tFIELD(f_%s__%s, nam_%s, fld_%s, %d, 0, 0, 0)\n"
, cor_rel_name, cor_fld_name, cor_fld_name, cor_src_fld_name, upd_flag);
ib_fprintf(ids, "#define f_%s__%s %d\n", cor_rel_name, cor_fld_name, fld_id);
}
ib_fprintf(relations, "END_RELATION\n");
EXEC SQL
CLOSE relation_join;
ib_fprintf(relations, "\n");
ib_fprintf(ids, "\n");
CHECK_CLOSE(relations, RELATIONS_H, "tmpcode1", "w", genDirectory);
CHECK_CLOSE(ids, IDS_H, "tmpcode2", "w", genDirectory);
}
static void build_fields_h(void){
/*******************************************
*
* b u i l d _ f i e l d s _ h
*
*******************************************
*
* Functional desciption
* Function creates the msgfac.h
* file which contains a listing of valid
* facilities for the error codes.
*
*******************************************/
IB_FILE *fields;
/* Open files in the current directory */
CHECK_OPEN(fields, FIELDS_H, "tmpcode3", "w");
add_text(fields, CSTYLE, license);
add_text(fields, CSTYLE, warn);
ib_fprintf(fields, "/*\n");
ib_fprintf(fields, " * MODULE: fields.h\n");
ib_fprintf(fields, " * DESCRIPTION: System relation definitions\n");
ib_fprintf(fields, " *\n");
ib_fprintf(fields, " */\n");
ib_fprintf(fields, "#ifndef BLOB_SIZE\n");
ib_fprintf(fields, "#define BLOB_SIZE 8\n");
ib_fprintf(fields, "#endif\n");
ib_fprintf(fields, "\n");
ib_fprintf(fields, "#define TIMESTAMP_SIZE 8\n");
ib_fprintf(fields, "\n");
char fld_name[31];
char cor_fld_name[31];
int fld_type;
int fld_subtype;
int fld_length;
EXEC SQL
DECLARE relation_fields CURSOR FOR
SELECT RDB$FIELD_NAME, RDB$FIELD_TYPE, RDB$FIELD_SUB_TYPE, RDB$FIELD_LENGTH
FROM RDB$FIELDS
WHERE RDB$SYSTEM_FLAG='1'
/* Open the cursor. */
EXEC SQL
OPEN relation_fields;
/*
* Select and display all rows.
*/
if (SQLCODE != 0)
printf("ERROR %d ",SQLCODE);
while (SQLCODE == 0)
{
EXEC SQL
FETCH relation_fields INTO :fld_name, :fld_type, :fld_subtype, :fld_length;
if (SQLCODE !=0)
break;
/*
* If FETCH returns with -100, the processing will jump
* to AllDone before the following printf is executed.
*/
sscanf(fld_name,"RDB$%s",cor_fld_name);
ib_fprintf(fields, "FIELD(fld_%-31s, nam_%-31s, "
, cor_fld_name, cor_fld_name);
switch(fld_type){
case blr_short:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_short","sizeof(SSHORT)","0");
break;
case blr_long:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_long","sizeof(SLONG)","0");
break;
case blr_quad:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_quad","unknown","0");
break;
case blr_float:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_float","unknown","0");
break;
case blr_d_float:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_d_float","unknown","0");
break;
case blr_sql_date:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_sql_date","unknown","0");
break;
case blr_sql_time:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_sql_time","unknown","0");
break;
case blr_text:
ib_fprintf(fields,"%-20s,%-15d,","dtype_text", fld_length);
switch(fld_subtype){
case 0:
ib_fprintf(fields,"%-25s,","0");
break;
case 3:
ib_fprintf(fields,"%-25s,","dsc_text_type_metadata");
break;
default:
ib_fprintf(fields,"%-25s%d,","Unknown",fld_subtype);
break;
}
break;
case blr_text2:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_text2","31","0");
break;
case blr_int64:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_int64","Unknown","0");
break;
case blr_double:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_double","sizeof(double)","0");
break;
case blr_timestamp:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_timestamp","TIMESTAMP_SIZE","0");
break;
case blr_varying:
ib_fprintf(fields,"%-20s,%-15d,%-25s,","dtype_varying",fld_length+2,"0");
break;
case blr_varying2:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_varying2","Unknown","0");
break;
case blr_cstring:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_cstring","unknown","0");
break;
case blr_cstring2:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_cstring2","unknown","0");
break;
case blr_blob_id:
ib_fprintf(fields,"%-20s,%-15s,%-25s,","dtype_blob_id","Unknown","0");
break;
case blr_blob:
ib_fprintf(fields,"%-20s,%-15s,","dtype_blob","BLOB_SIZE");
switch(fld_subtype){
case 1:
ib_fprintf(fields,"%-25s,","BLOB_text");
break;
case 2:
ib_fprintf(fields,"%-25s,","BLOB_blr");
break;
case 3:
ib_fprintf(fields,"%-25s,","BLOB_acl");
break;
case 5:
ib_fprintf(fields,"%-25s,","BLOB_summary");
break;
case 6:
ib_fprintf(fields,"%-25s,","BLOB_format");
break;
case 7:
ib_fprintf(fields,"%-25s,","BLOB_tra");
break;
case 8:
ib_fprintf(fields,"%-25s,","BLOB_extfile");
break;
default:
ib_fprintf(fields,"%-25s%d,","Unknown",fld_subtype);
break;
}
break;
}
if (strcmp(cor_fld_name,"DEFERRABLE")==0)
ib_fprintf(fields, " 0, dflt_no)\n");
else if (strcmp(cor_fld_name,"MATCH_OPTION")==0)
ib_fprintf(fields, " 0, dflt_full)\n");
else if (strcmp(cor_fld_name,"RULE")==0)
ib_fprintf(fields, " 0, dflt_restrict)\n");
else
ib_fprintf(fields, " 0, NULL)\n");
}
EXEC SQL
CLOSE relation_fields;
ib_fprintf(fields, "\n");
CHECK_CLOSE(fields, FIELDS_H, "tmpcode3", "w", genDirectory);
}
static void build_names_h(void){
/*******************************************
*
* b u i l d _ n a m e s _ h
*
*******************************************
*
* Functional desciption
* Function creates the names.
* file which contains a listing of
* ......
*
*******************************************/
IB_FILE *names;
/* Open files in the current directory */
CHECK_OPEN(names, NAMES_H, "tmpcode4", "w");
add_text(names, CSTYLE, license);
add_text(names, CSTYLE, warn);
ib_fprintf(names, "/*\n");
ib_fprintf(names, " * MODULE: names.h\n");
ib_fprintf(names, " * DESCRIPTION: System relation definitions\n");
ib_fprintf(names, " *\n");
ib_fprintf(names, " */\n");
char fld_name[31];
char cor_fld_name[31];
int upd_flag;
int fld_id;
EXEC SQL
DECLARE names_join CURSOR FOR
SELECT rdb$field_name FROM rdb$fields WHERE rdb$system_flag='1'
UNION SELECT rdb$relation_name FROM rdb$relations WHERE rdb$system_flag='1'
UNION SELECT rdb$field_name FROM rdb$relation_fields WHERE rdb$system_flag='1'
ORDER BY 1
/* Open the cursor. */
EXEC SQL
OPEN names_join;
/*
* Select and display all rows.
*/
while (SQLCODE == 0)
{
EXEC SQL
FETCH names_join INTO :fld_name;
if (SQLCODE !=0)
break;
/*
* If FETCH returns with -100, the processing will jump
* to AllDone before the following printf is executed.
*/
sscanf(fld_name,"RDB$%s",cor_fld_name);
ib_fprintf(names, "NAME(\"RDB$%s\", nam_%s)\n"
, cor_fld_name, cor_fld_name);
}
EXEC SQL
CLOSE names_join;
ib_fprintf(names, "\n");
CHECK_CLOSE(names, NAMES_H, "tmpcode4", "w", genDirectory);
}
/*******************************************
*
*
*
*******************************************/
static void move_if_not_identical( char* original, char* new_file, char *directory){
char origName[1000];
char buffer[1000];
#if defined(WIN_NT) && !defined(__GNUC__)
if ( directory != NULL) {
sprintf(origName,"%s\\%s", directory, original);
}
else {
sprintf(origName,".\\%s", original);
}
/*
* This is a trick to make on systems previous to W2K were apparently
* fc does not return a errorlevel, but find return it (1 found 0 not found)
* FC: appear only where there are no differences (and the switch /B is not used)
*/
sprintf(buffer, "fc %s %s | find \"FC:\" > nul", new_file, origName);
#else
if ( directory != NULL) {
sprintf(origName,"%s/%s", directory, original);
}
else {
sprintf(origName,"./%s", original);
}
sprintf(buffer, "cmp -s %s %s", new_file, origName);
#endif
/* If the new file is identical to the original, then don't update
the original */
if (system(buffer) == 0) {
ib_fprintf(ib_stderr, "No need to update %s\n", origName);
unlink(new_file);
}
else {
/* Original file is missing or different */
#if defined(WIN_NT) && !defined(__GNUC__)
sprintf(buffer, "move %s %s > nul", new_file, origName);
#else
sprintf(buffer, "mv -f %s %s", new_file, origName);
#endif
if (system(buffer) != 0) {
ib_fprintf(ib_stderr, "Error moving %s to %s!\n",
new_file, origName);
exit(FINI_ERROR);
}
else
ib_fprintf(ib_stderr, "Updated %s\n", origName);
}
}
static void add_text(IB_FILE * fd, int style, const char **text)
{
/*******************************************
*
* a d d _ t e x t
*
*******************************************
*
* Functional desciption
* Function adds text as comment
* in 'style' language
*
*******************************************/
const char **ptr;
switch (style) {
case CSTYLE:
ib_fprintf(fd, "/*\n");
break;
case PASSTYLE:
ib_fprintf(fd, "(*\n");
break;
case FTNSTYLE:
ib_fprintf(fd, "C --\n");
break;
default:
ib_fprintf(ib_stderr, "Error writing license\n");
exit(FINI_ERROR);
break;
}
for (ptr = text; *ptr; ++ptr) {
switch (style) {
case CSTYLE:
case PASSTYLE:
ib_fprintf(fd, " * ");
break;
case FTNSTYLE:
ib_fprintf(fd, "C -- ");
break;
}
ib_fprintf(fd, "%s\n", *ptr);
}
switch (style) {
case CSTYLE:
ib_fprintf(fd, " */\n");
break;
case PASSTYLE:
ib_fprintf(fd, " *)\n");
break;
case FTNSTYLE:
ib_fprintf(fd, "C --\n");
break;
}
}