-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
) | ||
) | ||
|