mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-28 04:03:03 +01:00
621 lines
16 KiB
Plaintext
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;
|
|
}
|
|
}
|