Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
nilswald committed Oct 26, 2023
1 parent e8aec83 commit 4421da2
Show file tree
Hide file tree
Showing 2 changed files with 285 additions and 0 deletions.
37 changes: 37 additions & 0 deletions functions/SFmSchema/json/REAMDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## SFmSchema.json() Custom Function

### Parameters

#### _tables

This can be used to filter tables in the current file. You can use list of table names and even wildcards.

Example: providing "Global¶C*" returns the table 'Global' along with all other tables starting with 'C'

#### _options

You can provide one or more keywords to specify the output:

- format: the json output will be formatted
- debug: adds the original outputs from Get( FieldType ) and FileMaker_Fields
- nocache: results are cached in global variable so subsequent calls are significantly faster. For developing or debugging you might want to disable this.
- standard: only standard fields are being returned. Global fields, calculations and summary fields will be excluded from the result.
- stored: like 'standard' but with additional stored calculations.
- comments: includes the field comment from the field definitions.
- nextvalue: includes the next value for auto-incrementing fields like numeric ids.

### Result

The result is a json object with the table names as keys. Every table then is an object with can have the following keys:

- fmType: can either be standard, global, calculation, summary
- dataType: text, number, container, date, time, timestamp
- hasIndex: true if there is an index on the field. False values are omitted.
- id: internal field id
- modCount: number of changes applied to the field's definition
- isStored: only for calculation fields if the value is stored
- repCount: only for repeating fields
- nextValue: optional result from GetNextSerialValue() function.
- comment: comment from field definitions, null values are omitted.
- debugFromFunction: result from Get( FieldType ) function.
- debugFromSql: row from internal FileMaker_Fields table
248 changes: 248 additions & 0 deletions functions/SFmSchema/json/SFmSChema.json_v1.fmfn
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/* SFmDatabase.schemaJson( _tables; _options )
@about output detailled schema info as json
@author Nils Waldherr <nils.waldherr@fmgarage.com>
@copyright ©2023 FMGARAGE.com
@version 1.0.0-100 - 24.10.2023 - NW:
@param list _tables = "" -- filter table names, use * as wildcard
@param list _options = "" -- format, standard, stored, debug, nocache, comments, nextvalue
@return json
*/
Case(

/* return version
----------------------------------------------------------------------------------
*/
_tables = "--version" or $_Db.inVersionMode; 1000000;


/* preconditions
----------------------------------------------------------------------------------
*/

// empty _param
//IstLeer( _param ); "ERROR: parameter _param must not be empty";


/* main
----------------------------------------------------------------------------------
*/
Case(
// write cache
IsEmpty( $$SFmSchema.json ) or Position( _options; "nocache"; 1; 1 );
Let(
[
// settings
column_separator = "<<,>>";
file = GetValue( Substitute( Get( FileName ); " ("; ¶ ); 1 );

// filter tables by name using wildcard
_tables = Lower( _tables );
_tables_count = ValueCount( _tables );
tables_filter_uses_wildcards = Position( _tables; "*"; 1; 1 );
tables_filter_wildcards = Case(
tables_filter_uses_wildcards;
While(
[
tables = "";
i = 1
];
i <= _tables_count;
[
table = GetValue( _tables; i );
tables = List(
tables;
Case( Position( table; "*"; 1; 1 ); Substitute( table; "*"; "%" ))
);
i=i+1
];
tables
)
);

// filter tables by exact name
tables_filter = Case(
// filter-out wildcards
not IsEmpty( _tables ) and tables_filter_uses_wildcards;
While(
[
tables = "";
i = 1
];
i <= _tables_count;
[
table = GetValue( _tables; i );
tables = List(
tables;
Case( not Position( table; "*"; 1; 1 ); table )
);
i=i+1
];
tables
);
_tables
);
table_filter = Substitute(
List(
// tables_filter
Case(
not IsEmpty( tables_filter );
" lower(TableName) in ('"
& Substitute( tables_filter; ¶; "', '" )
& "') "
);
Case(
not IsEmpty( tables_filter_wildcards );
" lower(TableName) like '"
& Substitute( tables_filter_wildcards; ¶; "' OR lower(TableName) like '" )
& "' "
)
);
"¶";
" OR "
);

// get tables
sql = "select * from FileMaker_Tables where lower(TableName) = lower(BaseTableName) "
& Case( not IsEmpty( table_filter ); " AND ( " & table_filter & " ) " );
tables = ExecuteSQL( sql; column_separator; ""; file; file & " (%" );


// compose fields sql

stored_only = Position( _options; "stored"; 1; 1);

sql = "select * from FileMaker_Fields where TableName = ? "
& Case(
// standard_only
Position( _options; "standard"; 1; 1);
" and FieldClass = 'Normal' and FieldType not like 'global %'";

// stored only
stored_only;
" and FieldClass IN ( 'Normal', 'Calculated' ) and FieldType not like 'global %'";
);


// foreach in tables
json = While(
[
json = "";
len = ValueCount( tables );
i = 1
];
i <= len;
[
list = Substitute( GetValue( tables; i ); column_separator; "¶" );
table = GetValue( list; 1 );
record_count = ExecuteSQL( "select count(*) from \"" & table & "\""; ""; "" );
json = JSONSetElement( json;
[ table & ".id"; GetValue( list; 2 ); JSONNumber ];
[ table & ".modCount"; GetValue( list; 5 ); JSONNumber ];
[ table & ".recordCount"; record_count; JSONNumber ]
);

// get fields for table
fields = ExecuteSQL( sql; column_separator; ""; table );
json = While(
[
json = json;
i = 1;
len = ValueCount( fields )
];
i <= len;
[
sql_field = Substitute( GetValue( fields; i ); column_separator; ¶ );
field = GetValue( sql_field; 2 );
get_field = Substitute( FieldType( Get( FileName ); table & "::" & field ); " "; ¶ );
type_fm_pre = Lower( GetValue( get_field; 1 ));

json = Case(

// exclude
type_fm_pre = "UnstoredCalc" and stored_only; json;

// include
Let(
[
type_fm = Case( type_fm_pre = "UnstoredCalc" or type_fm_pre = "StoredCalc"; "calculation"; type_fm_pre );
type_data = Lower ( GetValue( get_field; 2 ));
path = table & ".fields." & field & ".";
json = JSONSetElement ( json;
[path & "fmType"; type_fm; JSONString];
[path & "dataType"; type_data; JSONString];
[path & "id"; GetValue( sql_field; 4 ); JSONNumber];
[path & "modCount"; GetValue( sql_field; 7 ); JSONNumber]
);
// optional values

// comment
comment = Case(
Position( _options; "comments"; 1; 1 );
FieldComment( Get( FileName ); table & "::" & field )
);
json = Case(
IsEmpty( comment ); json;
JSONSetElement( json; path & "comment"; comment; JSONString )
);
// repCount
rep_count = GetValue( sql_field; 6 );
json = Case(
rep_count = 1; json;
JSONSetElement( json; path & "repCount"; rep_count; JSONNumber )
);
// hasIndex
json = Case(
GetValue( get_field; 3 ) <> "Indexed"; json;
JSONSetElement( json; path & "hasIndex"; 1; JSONBoolean )
);
// isStored
json = Case(
type_fm_pre <> "StoredCalc"; json;
JSONSetElement( json; path & "isStored"; 1; JSONBoolean )
);
// nextValue
next_value = Case(
Position( _options; "nextvalue"; 1; 1 ) and type_fm = "standard";
GetNextSerialValue ( file; table & "::" & field )
);
json = Case(
next_value < 1; json;
JSONSetElement( json; path & "nextValue"; next_value; JSONNumber )
);
// debug
json = Case(
not Position( _options; "debug"; 1; 1 ); json;
JSONSetElement( json;
[path & "debugFromFunction"; Substitute( get_field; ¶; " | "); JSONString];
[path & "debugFromSql"; Substitute( sql_field; ¶; " | "); JSONString]
)
)
];
json
)
);

// next
i = i+1
];
json
);



i = i+1
];
json
);
$$SFmSchema.json = json
];
""
)
)
& Case(
Position( _options; "format"; 1; 1 );
JSONFormatElements( $$SFmSchema.json );
$$SFmSchema.json
)
)

0 comments on commit 4421da2

Please sign in to comment.